]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'for-rmk' of git://git.pengutronix.de/git/imx/linux-2.6 into devel-stable
authorRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 5 Jan 2011 10:23:38 +0000 (10:23 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 5 Jan 2011 10:23:38 +0000 (10:23 +0000)
520 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/include/asm/hw_breakpoint.h
arch/arm/include/asm/system.h
arch/arm/include/asm/traps.h
arch/arm/kernel/Makefile
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/entry-header.S
arch/arm/kernel/ftrace.c
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/irq.c
arch/arm/kernel/iwmmxt.S
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_v6.c [new file with mode: 0644]
arch/arm/kernel/perf_event_v7.c [new file with mode: 0644]
arch/arm/kernel/perf_event_xscale.c [new file with mode: 0644]
arch/arm/kernel/pj4-cp0.c [new file with mode: 0644]
arch/arm/kernel/ptrace.c
arch/arm/kernel/smp.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-cns3xxx/cns3420vb.c
arch/arm/mach-cns3xxx/core.h
arch/arm/mach-cns3xxx/devices.c
arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
arch/arm/mach-cns3xxx/include/mach/pm.h [new file with mode: 0644]
arch/arm/mach-cns3xxx/pm.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/aemif.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/clock.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-tnetv107x.c
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-davinci/psc.c
arch/arm/mach-davinci/time.c
arch/arm/mach-davinci/tnetv107x.c
arch/arm/mach-dove/Kconfig
arch/arm/mach-dove/Makefile
arch/arm/mach-dove/cm-a510.c [new file with mode: 0644]
arch/arm/mach-dove/include/mach/dove.h
arch/arm/mach-dove/include/mach/gpio.h
arch/arm/mach-dove/mpp.c [new file with mode: 0644]
arch/arm/mach-dove/mpp.h [new file with mode: 0644]
arch/arm/mach-kirkwood/Kconfig
arch/arm/mach-kirkwood/ts219-setup.c
arch/arm/mach-kirkwood/ts41x-setup.c
arch/arm/mach-mmp/Kconfig
arch/arm/mach-mmp/Makefile
arch/arm/mach-mmp/brownstone.c [new file with mode: 0644]
arch/arm/mach-mmp/flint.c
arch/arm/mach-mmp/include/mach/mfp-mmp2.h
arch/arm/mach-mmp/include/mach/mmp2.h
arch/arm/mach-mmp/include/mach/regs-apmu.h
arch/arm/mach-mmp/jasper.c
arch/arm/mach-mmp/mmp2.c
arch/arm/mach-mmp/pxa910.c
arch/arm/mach-msm/Kconfig
arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-orion5x/Kconfig
arch/arm/mach-orion5x/Makefile
arch/arm/mach-orion5x/ls-chl-setup.c [new file with mode: 0644]
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/capc7117.c
arch/arm/mach-pxa/clock-pxa2xx.c [new file with mode: 0644]
arch/arm/mach-pxa/clock-pxa3xx.c [new file with mode: 0644]
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-pxa/cm-x2xx.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-evalboard.c [moved from arch/arm/mach-pxa/colibri-pxa270-evalboard.c with 51% similarity]
arch/arm/mach-pxa/colibri-pxa270-income.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/colibri-pxa300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/colibri-pxa3xx.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/cpufreq-pxa2xx.c
arch/arm/mach-pxa/csb726.c
arch/arm/mach-pxa/devices.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/ezx.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/h5000.c
arch/arm/mach-pxa/himalaya.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/include/mach/addr-map.h [new file with mode: 0644]
arch/arm/mach-pxa/include/mach/balloon3.h
arch/arm/mach-pxa/include/mach/colibri.h
arch/arm/mach-pxa/include/mach/hardware.h
arch/arm/mach-pxa/include/mach/irqs.h
arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
arch/arm/mach-pxa/include/mach/regs-intc.h
arch/arm/mach-pxa/include/mach/smemc.h [new file with mode: 0644]
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/mp900.c
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmt5.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/palmtreo.c
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/pcm027.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/pxa930.c
arch/arm/mach-pxa/pxa95x.c [new file with mode: 0644]
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/saar.c
arch/arm/mach-pxa/saarb.c [new file with mode: 0644]
arch/arm/mach-pxa/sleep.S
arch/arm/mach-pxa/smemc.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/tavorevb3.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-pxa/xcep.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-s3c2412/Kconfig
arch/arm/mach-s3c2416/Kconfig
arch/arm/mach-s3c2440/Kconfig
arch/arm/mach-s3c2440/s3c2440.c
arch/arm/mach-s3c2440/s3c2442.c
arch/arm/mach-s3c2443/Kconfig
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/board-mop500-keypads.c [new file with mode: 0644]
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/board-u5500-sdi.c [new file with mode: 0644]
arch/arm/mach-ux500/board-u5500.c
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/clock.h
arch/arm/mach-ux500/cpu-db5500.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-ux500/cpufreq.c [new file with mode: 0644]
arch/arm/mach-ux500/devices-common.c [new file with mode: 0644]
arch/arm/mach-ux500/devices-common.h [new file with mode: 0644]
arch/arm/mach-ux500/devices-db5500.c [deleted file]
arch/arm/mach-ux500/devices-db5500.h [new file with mode: 0644]
arch/arm/mach-ux500/devices-db8500.c
arch/arm/mach-ux500/devices-db8500.h [new file with mode: 0644]
arch/arm/mach-ux500/devices.c
arch/arm/mach-ux500/dma-db5500.c [new file with mode: 0644]
arch/arm/mach-ux500/include/mach/db5500-regs.h
arch/arm/mach-ux500/include/mach/db8500-regs.h
arch/arm/mach-ux500/include/mach/devices.h
arch/arm/mach-ux500/include/mach/gpio.h
arch/arm/mach-ux500/include/mach/hardware.h
arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
arch/arm/mach-ux500/include/mach/irqs.h
arch/arm/mach-ux500/include/mach/mbox-db5500.h [moved from arch/arm/mach-ux500/include/mach/mbox.h with 100% similarity]
arch/arm/mach-ux500/include/mach/prcmu-defs.h [new file with mode: 0644]
arch/arm/mach-ux500/include/mach/prcmu-regs.h
arch/arm/mach-ux500/include/mach/prcmu.h
arch/arm/mach-ux500/include/mach/setup.h
arch/arm/mach-ux500/include/mach/uncompress.h
arch/arm/mach-ux500/mbox-db5500.c [moved from arch/arm/mach-ux500/mbox.c with 99% similarity]
arch/arm/mach-ux500/modem-irq-db5500.c [moved from arch/arm/mach-ux500/modem_irq.c with 100% similarity]
arch/arm/mach-ux500/platsmp.c
arch/arm/mach-ux500/prcmu.c
arch/arm/mm/Kconfig
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/proc-macros.S
arch/arm/plat-nomadik/gpio.c
arch/arm/plat-nomadik/include/plat/pincfg.h
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/sram.c
arch/arm/plat-pxa/Makefile
arch/arm/plat-pxa/include/plat/mfp.h
arch/arm/plat-s3c24xx/cpu.c
arch/arm/plat-s3c24xx/gpiolib.c
arch/arm/plat-s3c24xx/include/plat/s3c244x.h
arch/arm/plat-samsung/gpio-config.c
arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
arch/arm/plat-versatile/sched-clock.c
arch/arm/tools/mach-types
arch/mn10300/kernel/gdb-io-serial.c
arch/mn10300/kernel/gdb-io-ttysm.c
arch/mn10300/kernel/gdb-stub.c
arch/sh/Kconfig
arch/sh/include/asm/unistd_32.h
arch/sh/kernel/syscalls_32.S
arch/sparc/include/asm/openprom.h
arch/sparc/include/asm/oplib_32.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/kernel/leon_kernel.c
arch/sparc/prom/Makefile
arch/sparc/prom/console_32.c
arch/sparc/prom/console_64.c
arch/sparc/prom/devops_32.c [deleted file]
arch/sparc/prom/devops_64.c [deleted file]
arch/sparc/prom/misc_64.c
arch/sparc/prom/printf.c
arch/sparc/prom/tree_32.c
arch/sparc/prom/tree_64.c
arch/x86/crypto/ghash-clmulni-intel_glue.c
arch/x86/include/asm/pvclock.h
arch/x86/kernel/pvclock.c
arch/x86/xen/time.c
block/bsg.c
drivers/acpi/ac.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/hest.c
drivers/acpi/battery.c
drivers/acpi/ec.c
drivers/acpi/osl.c
drivers/acpi/power.c
drivers/acpi/processor_thermal.c
drivers/acpi/sleep.c
drivers/atm/adummy.c
drivers/atm/ambassador.c
drivers/atm/atmtcp.c
drivers/atm/eni.c
drivers/atm/firestream.c
drivers/atm/fore200e.c
drivers/atm/he.c
drivers/atm/horizon.c
drivers/atm/idt77252.c
drivers/atm/iphase.c
drivers/atm/lanai.c
drivers/atm/nicstar.c
drivers/atm/solos-pci.c
drivers/atm/zatm.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/agp/intel-gtt.c
drivers/connector/connector.c
drivers/dma/Makefile
drivers/dma/at_hdmac.c
drivers/dma/fsldma.c
drivers/dma/fsldma.h
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/ioat/Makefile
drivers/dma/pch_dma.c
drivers/dma/ppc4xx/adma.c
drivers/edac/amd64_edac.c
drivers/edac/edac_core.h
drivers/edac/edac_mc.c
drivers/firewire/ohci.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/tc35892-gpio.c [deleted file]
drivers/gpio/tc3589x-gpio.c [new file with mode: 0644]
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_acpi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/hwmon/adm1026.c
drivers/hwmon/it87.c
drivers/hwmon/ltc4215.c
drivers/i2c/busses/i2c-intel-mid.c
drivers/idle/intel_idle.c
drivers/infiniband/core/uverbs_cmd.c
drivers/input/joystick/turbografx.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/gpio_keys_polled.c [new file with mode: 0644]
drivers/input/keyboard/tc3589x-keypad.c [new file with mode: 0644]
drivers/input/mouse/synaptics.h
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/md/md.c
drivers/md/raid10.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/tc35892.c [deleted file]
drivers/mfd/tc3589x.c [new file with mode: 0644]
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/nand/omap2.c
drivers/net/b44.c
drivers/net/benet/be_cmds.c
drivers/net/bnx2x/bnx2x.h
drivers/net/bnx2x/bnx2x_cmn.c
drivers/net/bnx2x/bnx2x_init_ops.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h
drivers/net/caif/caif_shm_u5500.c
drivers/net/caif/caif_shmcore.c
drivers/net/cxgb4/t4_hw.c
drivers/net/cxgb4vf/cxgb4vf_main.c
drivers/net/ehea/ehea_ethtool.c
drivers/net/ehea/ehea_main.c
drivers/net/enic/enic_main.c
drivers/net/ifb.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/phy/Kconfig
drivers/net/phy/icplus.c
drivers/net/pppoe.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_main.c
drivers/net/qlge/qlge_mpi.c
drivers/net/r8169.c
drivers/net/sfc/efx.c
drivers/net/sfc/net_driver.h
drivers/net/sfc/nic.c
drivers/net/stmmac/stmmac_main.c
drivers/net/tulip/dmfe.c
drivers/net/usb/hso.c
drivers/net/wan/hd64572.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/libertas/main.c
drivers/net/wireless/orinoco/main.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/scan.c
drivers/net/wireless/orinoco/scan.h
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/orinoco/wext.c
drivers/net/xen-netfront.c
drivers/pcmcia/Kconfig
drivers/pcmcia/Makefile
drivers/pcmcia/pxa2xx_balloon3.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/pxa2xx_colibri.c [new file with mode: 0644]
drivers/pcmcia/soc_common.h
drivers/pnp/pnpacpi/core.c
drivers/regulator/tps6586x-regulator.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/hpsa.c
drivers/scsi/osd/osd_initiator.c
drivers/scsi/pmcraid.c
drivers/scsi/pmcraid.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/serial/kgdboc.c
drivers/spi/dw_spi.c
drivers/usb/Kconfig
drivers/usb/atm/usbatm.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-cns3xxx.c [new file with mode: 0644]
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ohci-cns3xxx.c [new file with mode: 0644]
drivers/usb/host/ohci-hcd.c
drivers/vhost/vhost.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/modedb.c
drivers/video/pxa3xx-gcu.c [new file with mode: 0644]
drivers/video/pxa3xx-gcu.h [new file with mode: 0644]
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/orphan.c
fs/btrfs/super.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ceph/dir.c
fs/ceph/ioctl.h
fs/ceph/locks.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/cifs/Makefile
fs/cifs/README
fs/cifs/cifs_fs_sb.h
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/exec.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/super.c
fs/fuse/file.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/mount_clnt.c
fs/nfs/nfs4proc.c
fs/nfs/pagelist.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs3xdr.c
fs/nfsd/xdr4.h
fs/xfs/xfs_rename.c
include/acpi/video.h
include/drm/i915_drm.h
include/linux/acpi.h
include/linux/atmdev.h
include/linux/fs.h
include/linux/gpio_keys.h
include/linux/input.h
include/linux/mfd/tc35892.h [deleted file]
include/linux/mfd/tc3589x.h [new file with mode: 0644]
include/linux/mfd/wm8994/pdata.h
include/linux/nfs_fs.h
include/linux/nfs_page.h
include/linux/snmp.h
include/linux/video_output.h
include/net/sock.h
include/xen/interface/io/ring.h
kernel/printk.c
kernel/workqueue.c
mm/filemap.c
mm/mmap.c
mm/truncate.c
mm/vmscan.c
net/atm/atm_sysfs.c
net/atm/resources.c
net/atm/resources.h
net/bluetooth/sco.c
net/core/filter.c
net/core/timestamping.c
net/econet/af_econet.c
net/ipv4/proc.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/ip6_tunnel.c
net/ipv6/sit.c
net/l2tp/l2tp_ip.c
net/llc/af_llc.c
net/mac80211/rx.c
net/mac80211/tx.c
net/sctp/socket.c
net/socket.c
net/sunrpc/svc_xprt.c
net/x25/x25_link.c
net/xfrm/xfrm_state.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm_hubs.c
sound/soc/soc-core.c
tools/perf/builtin-record.c
tools/perf/util/header.c
tools/perf/util/symbol.c

index a91f30890011ddf69ba9b859484966c943db7fb5..b6426f15b4ae85f5469b962806004237b9b5607e 100644 (file)
@@ -173,12 +173,13 @@ prototypes:
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*launder_page) (struct page *);
 
 locking rules:
-       All except set_page_dirty may block
+       All except set_page_dirty and freepage may block
 
                        BKL     PageLocked(page)        i_mutex
 writepage:             no      yes, unlocks (see below)
@@ -193,6 +194,7 @@ perform_write:              no      n/a                     yes
 bmap:                  no
 invalidatepage:                no      yes
 releasepage:           no      yes
+freepage:              no      yes
 direct_IO:             no
 launder_page:          no      yes
 
@@ -288,6 +290,9 @@ buffers from the page in preparation for freeing it.  It returns zero to
 indicate that the buffers are (or may be) freeable.  If ->releasepage is zero,
 the kernel assumes that the fs has no private interest in the buffers.
 
+       ->freepage() is called when the kernel is done dropping the page
+from the page cache.
+
        ->launder_page() may be called prior to releasing a page if
 it is still found to be dirty. It returns zero if the page was successfully
 cleaned, or an error value if not. Note that in order to prevent the page
index 55c28b79d8dce3afcb239f45cc1cc62c44685d3c..20899e095e7e6879580b53aa9aa0282fb4b5ce63 100644 (file)
@@ -534,6 +534,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        struct page* (*get_xip_page)(struct address_space *, sector_t,
@@ -678,6 +679,12 @@ struct address_space_operations {
         need to ensure this.  Possibly it can clear the PageUptodate
         bit if it cannot free private data yet.
 
+  freepage: freepage is called once the page is no longer visible in
+        the page cache in order to allow the cleanup of any private
+       data. Since it may be called by the memory reclaimer, it
+       should not assume that the original address_space mapping still
+       exists, and it should not block.
+
   direct_IO: called by the generic read/write routines to perform
         direct_IO - that is IO requests which bypass the page cache
         and transfer data directly between the storage and the
index 1a1c27b9c557b2e07af18cb9b8c4e97c53c95c86..6a588873cf8d2da8b00f803a1dcd8d96841292bd 100644 (file)
@@ -559,14 +559,14 @@ W:        http://maxim.org.za/at91_26.html
 S:     Maintained
 
 ARM/BCMRING ARM ARCHITECTURE
-M:     Leo Chen <leochen@broadcom.com>
+M:     Jiandong Zheng <jdzheng@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-bcmring
 
 ARM/BCMRING MTD NAND DRIVER
-M:     Leo Chen <leochen@broadcom.com>
+M:     Jiandong Zheng <jdzheng@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
@@ -815,7 +815,7 @@ F:  drivers/mmc/host/msm_sdcc.c
 F:     drivers/mmc/host/msm_sdcc.h
 F:     drivers/serial/msm_serial.h
 F:     drivers/serial/msm_serial.c
-T:     git git://codeaurora.org/quic/kernel/dwalker/linux-msm.git
+T:     git git://codeaurora.org/quic/kernel/davidb/linux-msm.git
 S:     Maintained
 
 ARM/TOSA MACHINE SUPPORT
@@ -5932,7 +5932,6 @@ F:        include/linux/tty.h
 
 TULIP NETWORK DRIVERS
 M:     Grant Grundler <grundler@parisc-linux.org>
-M:     Kyle McMartin <kyle@mcmartin.ca>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/tulip/
@@ -6584,6 +6583,15 @@ F:       include/linux/mfd/wm8400*
 F:     include/sound/wm????.h
 F:     sound/soc/codecs/wm*
 
+WORKQUEUE
+M:     Tejun Heo <tj@kernel.org>
+L:     linux-kernel@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git
+S:     Maintained
+F:     include/linux/workqueue.h
+F:     kernel/workqueue.c
+F:     Documentation/workqueue.txt
+
 X.25 NETWORK LAYER
 M:     Andrew Hendry <andrew.hendry@gmail.com>
 L:     linux-x25@vger.kernel.org
index 3d94974542eac52bec7078dc9f9a70bcb46596d5..5aa44278d95686e9719f38592599b094a72a1366 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 37
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index 0f3417065d136edf95755cbe74f5b84903b1a7fa..fac58916adecf15dcd7d868d010dcc9bb999b9be 100644 (file)
@@ -14,6 +14,7 @@ config ARM
        select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
        select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
        select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
+       select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZO
@@ -805,6 +806,7 @@ config ARCH_U8500
        select GENERIC_CLOCKEVENTS
        select COMMON_CLKDEV
        select ARCH_REQUIRE_GPIOLIB
+       select ARCH_HAS_CPUFREQ
        help
          Support for ST-Ericsson's Ux500 architecture
 
@@ -1009,8 +1011,8 @@ source arch/arm/mm/Kconfig
 
 config IWMMXT
        bool "Enable iWMMXt support"
-       depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK
-       default y if PXA27x || PXA3xx || ARCH_MMP
+       depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
+       default y if PXA27x || PXA3xx || PXA95x || ARCH_MMP
        help
          Enable support for iWMMXt context switching at run time if
          running on a CPU that supports it.
@@ -1215,10 +1217,11 @@ config SMP
        depends on EXPERIMENTAL
        depends on GENERIC_CLOCKEVENTS
        depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
-                MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
-                ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+                MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
+                ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
+                ARCH_MSM_SCORPIONMP
        select USE_GENERIC_SMP_HELPERS
-       select HAVE_ARM_SCU
+       select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
@@ -1293,6 +1296,7 @@ config NR_CPUS
 config HOTPLUG_CPU
        bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
        depends on SMP && HOTPLUG && EXPERIMENTAL
+       depends on !ARCH_MSM
        help
          Say Y here to experiment with turning CPUs off and on.  CPUs
          can be controlled through /sys/devices/system/cpu.
@@ -1301,7 +1305,7 @@ config LOCAL_TIMERS
        bool "Use local timer interrupts"
        depends on SMP
        default y
-       select HAVE_ARM_TWD
+       select HAVE_ARM_TWD if !ARCH_MSM_SCORPIONMP
        help
          Enable support for local timers on SMP platforms, rather then the
          legacy IPI broadcast method.  Local timers allows the system
@@ -1321,7 +1325,7 @@ config HZ
 
 config THUMB2_KERNEL
        bool "Compile the kernel in Thumb-2 mode"
-       depends on CPU_V7 && EXPERIMENTAL
+       depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
        select AEABI
        select ARM_ASM_UNIFIED
        help
@@ -1769,7 +1773,7 @@ comment "At least one emulation must be selected"
 
 config FPE_NWFPE
        bool "NWFPE math emulation"
-       depends on !AEABI || OABI_COMPAT
+       depends on (!AEABI || OABI_COMPAT) && !THUMB2_KERNEL
        ---help---
          Say Y to include the NWFPE floating point emulator in the kernel.
          This is necessary to run most binaries. Linux does not currently
index 2fd0b99afc4bc849cd448780358fa5fdd68ff644..eac62085f5b2add52908abe350990854caf8a5b2 100644 (file)
@@ -23,7 +23,7 @@ config STRICT_DEVMEM
 config FRAME_POINTER
        bool
        depends on !THUMB2_KERNEL
-       default y if !ARM_UNWIND
+       default y if !ARM_UNWIND || FUNCTION_GRAPH_TRACER
        help
          If you say N here, the resulting kernel will be slightly smaller and
          faster. However, if neither FRAME_POINTER nor ARM_UNWIND are enabled,
index 4d8ae9d67abef507217bcc4fba63861e7b853ae4..f389b2704d82110226254551e873d18f6c93a69c 100644 (file)
@@ -20,8 +20,8 @@ struct arch_hw_breakpoint_ctrl {
 struct arch_hw_breakpoint {
        u32     address;
        u32     trigger;
-       struct perf_event *suspended_wp;
-       struct arch_hw_breakpoint_ctrl ctrl;
+       struct  arch_hw_breakpoint_ctrl step_ctrl;
+       struct  arch_hw_breakpoint_ctrl ctrl;
 };
 
 static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
index 1120f18a6b17695e48c37a6b4d1d7e50d306e478..ec4327a4653d45c7e1e3fe6bb1e142d8fadce2e8 100644 (file)
 #include <asm/outercache.h>
 
 #define __exception    __attribute__((section(".exception.text")))
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#define __exception_irq_entry  __irq_entry
+#else
+#define __exception_irq_entry  __exception
+#endif
 
 struct thread_info;
 struct task_struct;
index 491960bf42602e9c509a32d382815a42b3089047..124475afb00719a5da9ceda00c4883358dc8052a 100644 (file)
@@ -15,13 +15,32 @@ struct undef_hook {
 void register_undef_hook(struct undef_hook *hook);
 void unregister_undef_hook(struct undef_hook *hook);
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+static inline int __in_irqentry_text(unsigned long ptr)
+{
+       extern char __irqentry_text_start[];
+       extern char __irqentry_text_end[];
+
+       return ptr >= (unsigned long)&__irqentry_text_start &&
+              ptr < (unsigned long)&__irqentry_text_end;
+}
+#else
+static inline int __in_irqentry_text(unsigned long ptr)
+{
+       return 0;
+}
+#endif
+
 static inline int in_exception_text(unsigned long ptr)
 {
        extern char __exception_text_start[];
        extern char __exception_text_end[];
+       int in;
+
+       in = ptr >= (unsigned long)&__exception_text_start &&
+            ptr < (unsigned long)&__exception_text_end;
 
-       return ptr >= (unsigned long)&__exception_text_start &&
-              ptr < (unsigned long)&__exception_text_end;
+       return in ? : __in_irqentry_text(ptr);
 }
 
 extern void __init early_trap_init(void);
index 5b9b268f4fbb368ecc34942c6bebed1c421beaca..c73abe4b7e7274e030928f1e702c98b7ddb07e0f 100644 (file)
@@ -5,7 +5,7 @@
 CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o        := -DTEXT_OFFSET=$(TEXT_OFFSET)
 
-ifdef CONFIG_DYNAMIC_FTRACE
+ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 endif
 
@@ -33,6 +33,7 @@ obj-$(CONFIG_SMP)             += smp.o
 obj-$(CONFIG_HAVE_ARM_SCU)     += smp_scu.o
 obj-$(CONFIG_HAVE_ARM_TWD)     += smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER)    += ftrace.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_KPROBES)          += kprobes.o kprobes-decode.o
 obj-$(CONFIG_ATAGS_PROC)       += atags.o
@@ -50,6 +51,7 @@ AFLAGS_crunch-bits.o          := -Wa,-mcpu=ep9312
 obj-$(CONFIG_CPU_XSCALE)       += xscale-cp0.o
 obj-$(CONFIG_CPU_XSC3)         += xscale-cp0.o
 obj-$(CONFIG_CPU_MOHAWK)       += xscale-cp0.o
+obj-$(CONFIG_CPU_PJ4)          += pj4-cp0.o
 obj-$(CONFIG_IWMMXT)           += iwmmxt.o
 obj-$(CONFIG_CPU_HAS_PMU)      += pmu.o
 obj-$(CONFIG_HW_PERF_EVENTS)   += perf_event.o
index bb96a7d4bbf55464a4069830657334e23fa72449..36199ffc4cc21a3d7c83282340f8829fd1775050 100644 (file)
@@ -198,6 +198,7 @@ __dabt_svc:
        @
        @ set desired IRQ state, then call main handler
        @
+       debug_entry r1
        msr     cpsr_c, r9
        mov     r2, sp
        bl      do_DataAbort
@@ -324,6 +325,7 @@ __pabt_svc:
 #else
        bl      CPU_PABORT_HANDLER
 #endif
+       debug_entry r1
        msr     cpsr_c, r9                      @ Maybe enable interrupts
        mov     r2, sp                          @ regs
        bl      do_PrefetchAbort                @ call abort handler
@@ -439,6 +441,7 @@ __dabt_usr:
        @
        @ IRQs on, then call the main handler
        @
+       debug_entry r1
        enable_irq
        mov     r2, sp
        adr     lr, BSYM(ret_from_exception)
@@ -703,6 +706,7 @@ __pabt_usr:
 #else
        bl      CPU_PABORT_HANDLER
 #endif
+       debug_entry r1
        enable_irq                              @ Enable interrupts
        mov     r2, sp                          @ regs
        bl      do_PrefetchAbort                @ call abort handler
index 8bfa98757cd2f3fc9ef128011944a55fa7838ffd..aae802ee12f86bad23e8fd2430ce5d206da28036 100644 (file)
@@ -141,98 +141,170 @@ ENDPROC(ret_from_fork)
 #endif
 #endif
 
-#ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(__gnu_mcount_nc)
-       mov     ip, lr
-       ldmia   sp!, {lr}
-       mov     pc, ip
-ENDPROC(__gnu_mcount_nc)
+.macro __mcount suffix
+       mcount_enter
+       ldr     r0, =ftrace_trace_function
+       ldr     r2, [r0]
+       adr     r0, .Lftrace_stub
+       cmp     r0, r2
+       bne     1f
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       ldr     r1, =ftrace_graph_return
+       ldr     r2, [r1]
+       cmp     r0, r2
+       bne     ftrace_graph_caller\suffix
+
+       ldr     r1, =ftrace_graph_entry
+       ldr     r2, [r1]
+       ldr     r0, =ftrace_graph_entry_stub
+       cmp     r0, r2
+       bne     ftrace_graph_caller\suffix
+#endif
 
-ENTRY(ftrace_caller)
-       stmdb   sp!, {r0-r3, lr}
-       mov     r0, lr
+       mcount_exit
+
+1:     mcount_get_lr   r1                      @ lr of instrumented func
+       mov     r0, lr                          @ instrumented function
+       sub     r0, r0, #MCOUNT_INSN_SIZE
+       adr     lr, BSYM(2f)
+       mov     pc, r2
+2:     mcount_exit
+.endm
+
+.macro __ftrace_caller suffix
+       mcount_enter
+
+       mcount_get_lr   r1                      @ lr of instrumented func
+       mov     r0, lr                          @ instrumented function
        sub     r0, r0, #MCOUNT_INSN_SIZE
-       ldr     r1, [sp, #20]
 
-       .global ftrace_call
-ftrace_call:
+       .globl ftrace_call\suffix
+ftrace_call\suffix:
        bl      ftrace_stub
-       ldmia   sp!, {r0-r3, ip, lr}
-       mov     pc, ip
-ENDPROC(ftrace_caller)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       .globl ftrace_graph_call\suffix
+ftrace_graph_call\suffix:
+       mov     r0, r0
+#endif
+
+       mcount_exit
+.endm
+
+.macro __ftrace_graph_caller
+       sub     r0, fp, #4              @ &lr of instrumented routine (&parent)
+#ifdef CONFIG_DYNAMIC_FTRACE
+       @ called from __ftrace_caller, saved in mcount_enter
+       ldr     r1, [sp, #16]           @ instrumented routine (func)
+#else
+       @ called from __mcount, untouched in lr
+       mov     r1, lr                  @ instrumented routine (func)
+#endif
+       sub     r1, r1, #MCOUNT_INSN_SIZE
+       mov     r2, fp                  @ frame pointer
+       bl      prepare_ftrace_return
+       mcount_exit
+.endm
 
 #ifdef CONFIG_OLD_MCOUNT
+/*
+ * mcount
+ */
+
+.macro mcount_enter
+       stmdb   sp!, {r0-r3, lr}
+.endm
+
+.macro mcount_get_lr reg
+       ldr     \reg, [fp, #-4]
+.endm
+
+.macro mcount_exit
+       ldr     lr, [fp, #-4]
+       ldmia   sp!, {r0-r3, pc}
+.endm
+
 ENTRY(mcount)
+#ifdef CONFIG_DYNAMIC_FTRACE
        stmdb   sp!, {lr}
        ldr     lr, [fp, #-4]
        ldmia   sp!, {pc}
+#else
+       __mcount _old
+#endif
 ENDPROC(mcount)
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 ENTRY(ftrace_caller_old)
-       stmdb   sp!, {r0-r3, lr}
-       ldr     r1, [fp, #-4]
-       mov     r0, lr
-       sub     r0, r0, #MCOUNT_INSN_SIZE
-
-       .globl ftrace_call_old
-ftrace_call_old:
-       bl      ftrace_stub
-       ldr     lr, [fp, #-4]                   @ restore lr
-       ldmia   sp!, {r0-r3, pc}
+       __ftrace_caller _old
 ENDPROC(ftrace_caller_old)
 #endif
 
-#else
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller_old)
+       __ftrace_graph_caller
+ENDPROC(ftrace_graph_caller_old)
+#endif
 
-ENTRY(__gnu_mcount_nc)
+.purgem mcount_enter
+.purgem mcount_get_lr
+.purgem mcount_exit
+#endif
+
+/*
+ * __gnu_mcount_nc
+ */
+
+.macro mcount_enter
        stmdb   sp!, {r0-r3, lr}
-       ldr     r0, =ftrace_trace_function
-       ldr     r2, [r0]
-       adr     r0, .Lftrace_stub
-       cmp     r0, r2
-       bne     gnu_trace
+.endm
+
+.macro mcount_get_lr reg
+       ldr     \reg, [sp, #20]
+.endm
+
+.macro mcount_exit
        ldmia   sp!, {r0-r3, ip, lr}
        mov     pc, ip
+.endm
 
-gnu_trace:
-       ldr     r1, [sp, #20]                   @ lr of instrumented routine
-       mov     r0, lr
-       sub     r0, r0, #MCOUNT_INSN_SIZE
-       adr     lr, BSYM(1f)
-       mov     pc, r2
-1:
-       ldmia   sp!, {r0-r3, ip, lr}
+ENTRY(__gnu_mcount_nc)
+#ifdef CONFIG_DYNAMIC_FTRACE
+       mov     ip, lr
+       ldmia   sp!, {lr}
        mov     pc, ip
+#else
+       __mcount
+#endif
 ENDPROC(__gnu_mcount_nc)
 
-#ifdef CONFIG_OLD_MCOUNT
-/*
- * This is under an ifdef in order to force link-time errors for people trying
- * to build with !FRAME_POINTER with a GCC which doesn't use the new-style
- * mcount.
- */
-ENTRY(mcount)
-       stmdb   sp!, {r0-r3, lr}
-       ldr     r0, =ftrace_trace_function
-       ldr     r2, [r0]
-       adr     r0, ftrace_stub
-       cmp     r0, r2
-       bne     trace
-       ldr     lr, [fp, #-4]                   @ restore lr
-       ldmia   sp!, {r0-r3, pc}
+#ifdef CONFIG_DYNAMIC_FTRACE
+ENTRY(ftrace_caller)
+       __ftrace_caller
+ENDPROC(ftrace_caller)
+#endif
 
-trace:
-       ldr     r1, [fp, #-4]                   @ lr of instrumented routine
-       mov     r0, lr
-       sub     r0, r0, #MCOUNT_INSN_SIZE
-       mov     lr, pc
-       mov     pc, r2
-       ldr     lr, [fp, #-4]                   @ restore lr
-       ldmia   sp!, {r0-r3, pc}
-ENDPROC(mcount)
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller)
+       __ftrace_graph_caller
+ENDPROC(ftrace_graph_caller)
 #endif
 
-#endif /* CONFIG_DYNAMIC_FTRACE */
+.purgem mcount_enter
+.purgem mcount_get_lr
+.purgem mcount_exit
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       .globl return_to_handler
+return_to_handler:
+       stmdb   sp!, {r0-r3}
+       mov     r0, fp                  @ frame pointer
+       bl      ftrace_return_to_handler
+       mov     lr, r0                  @ r0 has real ret addr
+       ldmia   sp!, {r0-r3}
+       mov     pc, lr
+#endif
 
 ENTRY(ftrace_stub)
 .Lftrace_stub:
index d93f976fb3893638900e8ff4660f1c6891a21457..ae946490016863a131f3b77b1552795d3e931c0f 100644 (file)
        .endm
 #endif /* !CONFIG_THUMB2_KERNEL */
 
+       @
+       @ Debug exceptions are taken as prefetch or data aborts.
+       @ We must disable preemption during the handler so that
+       @ we can access the debug registers safely.
+       @
+       .macro  debug_entry, fsr
+#if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT)
+       ldr     r4, =0x40f              @ mask out fsr.fs
+       and     r5, r4, \fsr
+       cmp     r5, #2                  @ debug exception
+       bne     1f
+       get_thread_info r10
+       ldr     r6, [r10, #TI_PREEMPT]  @ get preempt count
+       add     r11, r6, #1             @ increment it
+       str     r11, [r10, #TI_PREEMPT]
+1:
+#endif
+       .endm
+
 /*
  * These are the registers used in the syscall handler, and allow us to
  * have in theory up to 7 arguments to a function - r0 to r6.
index 971ac8c36ea775ca58702cb0f17c18aba7b1c4a7..c0062ad1e847b5a1ab68a21a8ed3f4d37eb9ce2a 100644 (file)
@@ -24,6 +24,7 @@
 #define        NOP             0xe8bd4000      /* pop {lr} */
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 #ifdef CONFIG_OLD_MCOUNT
 #define OLD_MCOUNT_ADDR        ((unsigned long) mcount)
 #define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
@@ -59,9 +60,9 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
 }
 #endif
 
-/* construct a branch (BL) instruction to addr */
 #ifdef CONFIG_THUMB2_KERNEL
-static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
+                                      bool link)
 {
        unsigned long s, j1, j2, i1, i2, imm10, imm11;
        unsigned long first, second;
@@ -83,15 +84,22 @@ static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
        j2 = (!i2) ^ s;
 
        first = 0xf000 | (s << 10) | imm10;
-       second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11;
+       second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
+       if (link)
+               second |= 1 << 14;
 
        return (second << 16) | first;
 }
 #else
-static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
+                                      bool link)
 {
+       unsigned long opcode = 0xea000000;
        long offset;
 
+       if (link)
+               opcode |= 1 << 24;
+
        offset = (long)addr - (long)(pc + 8);
        if (unlikely(offset < -33554432 || offset > 33554428)) {
                /* Can't generate branches that far (from ARM ARM). Ftrace
@@ -103,10 +111,15 @@ static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
 
        offset = (offset >> 2) & 0x00ffffff;
 
-       return 0xeb000000 | offset;
+       return opcode | offset;
 }
 #endif
 
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+{
+       return ftrace_gen_branch(pc, addr, true);
+}
+
 static int ftrace_modify_code(unsigned long pc, unsigned long old,
                              unsigned long new)
 {
@@ -193,3 +206,83 @@ int __init ftrace_dyn_arch_init(void *data)
 
        return 0;
 }
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+                          unsigned long frame_pointer)
+{
+       unsigned long return_hooker = (unsigned long) &return_to_handler;
+       struct ftrace_graph_ent trace;
+       unsigned long old;
+       int err;
+
+       if (unlikely(atomic_read(&current->tracing_graph_pause)))
+               return;
+
+       old = *parent;
+       *parent = return_hooker;
+
+       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+                                      frame_pointer);
+       if (err == -EBUSY) {
+               *parent = old;
+               return;
+       }
+
+       trace.func = self_addr;
+
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace)) {
+               current->curr_ret_stack--;
+               *parent = old;
+       }
+}
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern unsigned long ftrace_graph_call;
+extern unsigned long ftrace_graph_call_old;
+extern void ftrace_graph_caller_old(void);
+
+static int __ftrace_modify_caller(unsigned long *callsite,
+                                 void (*func) (void), bool enable)
+{
+       unsigned long caller_fn = (unsigned long) func;
+       unsigned long pc = (unsigned long) callsite;
+       unsigned long branch = ftrace_gen_branch(pc, caller_fn, false);
+       unsigned long nop = 0xe1a00000; /* mov r0, r0 */
+       unsigned long old = enable ? nop : branch;
+       unsigned long new = enable ? branch : nop;
+
+       return ftrace_modify_code(pc, old, new);
+}
+
+static int ftrace_modify_graph_caller(bool enable)
+{
+       int ret;
+
+       ret = __ftrace_modify_caller(&ftrace_graph_call,
+                                    ftrace_graph_caller,
+                                    enable);
+
+#ifdef CONFIG_OLD_MCOUNT
+       if (!ret)
+               ret = __ftrace_modify_caller(&ftrace_graph_call_old,
+                                            ftrace_graph_caller_old,
+                                            enable);
+#endif
+
+       return ret;
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+       return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+       return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index 21e3a4ab3b8c58047304b694aa8161b9ebbf1c31..c9f3f046757046010ea1f95d13321f676f202d0a 100644 (file)
@@ -24,6 +24,7 @@
 #define pr_fmt(fmt) "hw-breakpoint: " fmt
 
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/smp.h>
@@ -44,6 +45,7 @@ static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
 
 /* Number of BRP/WRP registers on this CPU. */
 static int core_num_brps;
+static int core_num_reserved_brps;
 static int core_num_wrps;
 
 /* Debug architecture version. */
@@ -52,87 +54,6 @@ static u8 debug_arch;
 /* Maximum supported watchpoint length. */
 static u8 max_watchpoint_len;
 
-/* Determine number of BRP registers available. */
-static int get_num_brps(void)
-{
-       u32 didr;
-       ARM_DBG_READ(c0, 0, didr);
-       return ((didr >> 24) & 0xf) + 1;
-}
-
-/* Determine number of WRP registers available. */
-static int get_num_wrps(void)
-{
-       /*
-        * FIXME: When a watchpoint fires, the only way to work out which
-        * watchpoint it was is by disassembling the faulting instruction
-        * and working out the address of the memory access.
-        *
-        * Furthermore, we can only do this if the watchpoint was precise
-        * since imprecise watchpoints prevent us from calculating register
-        * based addresses.
-        *
-        * For the time being, we only report 1 watchpoint register so we
-        * always know which watchpoint fired. In the future we can either
-        * add a disassembler and address generation emulator, or we can
-        * insert a check to see if the DFAR is set on watchpoint exception
-        * entry [the ARM ARM states that the DFAR is UNKNOWN, but
-        * experience shows that it is set on some implementations].
-        */
-
-#if 0
-       u32 didr, wrps;
-       ARM_DBG_READ(c0, 0, didr);
-       return ((didr >> 28) & 0xf) + 1;
-#endif
-
-       return 1;
-}
-
-int hw_breakpoint_slots(int type)
-{
-       /*
-        * We can be called early, so don't rely on
-        * our static variables being initialised.
-        */
-       switch (type) {
-       case TYPE_INST:
-               return get_num_brps();
-       case TYPE_DATA:
-               return get_num_wrps();
-       default:
-               pr_warning("unknown slot type: %d\n", type);
-               return 0;
-       }
-}
-
-/* Determine debug architecture. */
-static u8 get_debug_arch(void)
-{
-       u32 didr;
-
-       /* Do we implement the extended CPUID interface? */
-       if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
-               pr_warning("CPUID feature registers not supported. "
-                               "Assuming v6 debug is present.\n");
-               return ARM_DEBUG_ARCH_V6;
-       }
-
-       ARM_DBG_READ(c0, 0, didr);
-       return (didr >> 16) & 0xf;
-}
-
-/* Does this core support mismatch breakpoints? */
-static int core_has_mismatch_bps(void)
-{
-       return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1;
-}
-
-u8 arch_get_debug_arch(void)
-{
-       return debug_arch;
-}
-
 #define READ_WB_REG_CASE(OP2, M, VAL)          \
        case ((OP2 << 4) + M):                  \
                ARM_DBG_READ(c ## M, OP2, VAL); \
@@ -210,6 +131,94 @@ static void write_wb_reg(int n, u32 val)
        isb();
 }
 
+/* Determine debug architecture. */
+static u8 get_debug_arch(void)
+{
+       u32 didr;
+
+       /* Do we implement the extended CPUID interface? */
+       if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
+               pr_warning("CPUID feature registers not supported. "
+                               "Assuming v6 debug is present.\n");
+               return ARM_DEBUG_ARCH_V6;
+       }
+
+       ARM_DBG_READ(c0, 0, didr);
+       return (didr >> 16) & 0xf;
+}
+
+u8 arch_get_debug_arch(void)
+{
+       return debug_arch;
+}
+
+/* Determine number of BRP register available. */
+static int get_num_brp_resources(void)
+{
+       u32 didr;
+       ARM_DBG_READ(c0, 0, didr);
+       return ((didr >> 24) & 0xf) + 1;
+}
+
+/* Does this core support mismatch breakpoints? */
+static int core_has_mismatch_brps(void)
+{
+       return (get_debug_arch() >= ARM_DEBUG_ARCH_V7_ECP14 &&
+               get_num_brp_resources() > 1);
+}
+
+/* Determine number of usable WRPs available. */
+static int get_num_wrps(void)
+{
+       /*
+        * FIXME: When a watchpoint fires, the only way to work out which
+        * watchpoint it was is by disassembling the faulting instruction
+        * and working out the address of the memory access.
+        *
+        * Furthermore, we can only do this if the watchpoint was precise
+        * since imprecise watchpoints prevent us from calculating register
+        * based addresses.
+        *
+        * Providing we have more than 1 breakpoint register, we only report
+        * a single watchpoint register for the time being. This way, we always
+        * know which watchpoint fired. In the future we can either add a
+        * disassembler and address generation emulator, or we can insert a
+        * check to see if the DFAR is set on watchpoint exception entry
+        * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
+        * that it is set on some implementations].
+        */
+
+#if 0
+       int wrps;
+       u32 didr;
+       ARM_DBG_READ(c0, 0, didr);
+       wrps = ((didr >> 28) & 0xf) + 1;
+#endif
+       int wrps = 1;
+
+       if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())
+               wrps = get_num_brp_resources() - 1;
+
+       return wrps;
+}
+
+/* We reserve one breakpoint for each watchpoint. */
+static int get_num_reserved_brps(void)
+{
+       if (core_has_mismatch_brps())
+               return get_num_wrps();
+       return 0;
+}
+
+/* Determine number of usable BRPs available. */
+static int get_num_brps(void)
+{
+       int brps = get_num_brp_resources();
+       if (core_has_mismatch_brps())
+               brps -= get_num_reserved_brps();
+       return brps;
+}
+
 /*
  * In order to access the breakpoint/watchpoint control registers,
  * we must be running in debug monitor mode. Unfortunately, we can
@@ -230,8 +239,12 @@ static int enable_monitor_mode(void)
                goto out;
        }
 
+       /* If monitor mode is already enabled, just return. */
+       if (dscr & ARM_DSCR_MDBGEN)
+               goto out;
+
        /* Write to the corresponding DSCR. */
-       switch (debug_arch) {
+       switch (get_debug_arch()) {
        case ARM_DEBUG_ARCH_V6:
        case ARM_DEBUG_ARCH_V6_1:
                ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
@@ -246,15 +259,30 @@ static int enable_monitor_mode(void)
 
        /* Check that the write made it through. */
        ARM_DBG_READ(c1, 0, dscr);
-       if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
-                               "failed to enable monitor mode.")) {
+       if (!(dscr & ARM_DSCR_MDBGEN))
                ret = -EPERM;
-       }
 
 out:
        return ret;
 }
 
+int hw_breakpoint_slots(int type)
+{
+       /*
+        * We can be called early, so don't rely on
+        * our static variables being initialised.
+        */
+       switch (type) {
+       case TYPE_INST:
+               return get_num_brps();
+       case TYPE_DATA:
+               return get_num_wrps();
+       default:
+               pr_warning("unknown slot type: %d\n", type);
+               return 0;
+       }
+}
+
 /*
  * Check if 8-bit byte-address select is available.
  * This clobbers WRP 0.
@@ -268,9 +296,6 @@ static u8 get_max_wp_len(void)
        if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
                goto out;
 
-       if (enable_monitor_mode())
-               goto out;
-
        memset(&ctrl, 0, sizeof(ctrl));
        ctrl.len = ARM_BREAKPOINT_LEN_8;
        ctrl_reg = encode_ctrl_reg(ctrl);
@@ -289,23 +314,6 @@ u8 arch_get_max_wp_len(void)
        return max_watchpoint_len;
 }
 
-/*
- * Handler for reactivating a suspended watchpoint when the single
- * step `mismatch' breakpoint is triggered.
- */
-static void wp_single_step_handler(struct perf_event *bp, int unused,
-                                  struct perf_sample_data *data,
-                                  struct pt_regs *regs)
-{
-       perf_event_enable(counter_arch_bp(bp)->suspended_wp);
-       unregister_hw_breakpoint(bp);
-}
-
-static int bp_is_single_step(struct perf_event *bp)
-{
-       return bp->overflow_handler == wp_single_step_handler;
-}
-
 /*
  * Install a perf counter breakpoint.
  */
@@ -314,30 +322,41 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
        struct arch_hw_breakpoint *info = counter_arch_bp(bp);
        struct perf_event **slot, **slots;
        int i, max_slots, ctrl_base, val_base, ret = 0;
+       u32 addr, ctrl;
 
        /* Ensure that we are in monitor mode and halting mode is disabled. */
        ret = enable_monitor_mode();
        if (ret)
                goto out;
 
+       addr = info->address;
+       ctrl = encode_ctrl_reg(info->ctrl) | 0x1;
+
        if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
                /* Breakpoint */
                ctrl_base = ARM_BASE_BCR;
                val_base = ARM_BASE_BVR;
-               slots = __get_cpu_var(bp_on_reg);
-               max_slots = core_num_brps - 1;
-
-               if (bp_is_single_step(bp)) {
-                       info->ctrl.mismatch = 1;
-                       i = max_slots;
-                       slots[i] = bp;
-                       goto setup;
+               slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
+               max_slots = core_num_brps;
+               if (info->step_ctrl.enabled) {
+                       /* Override the breakpoint data with the step data. */
+                       addr = info->trigger & ~0x3;
+                       ctrl = encode_ctrl_reg(info->step_ctrl);
                }
        } else {
                /* Watchpoint */
-               ctrl_base = ARM_BASE_WCR;
-               val_base = ARM_BASE_WVR;
-               slots = __get_cpu_var(wp_on_reg);
+               if (info->step_ctrl.enabled) {
+                       /* Install into the reserved breakpoint region. */
+                       ctrl_base = ARM_BASE_BCR + core_num_brps;
+                       val_base = ARM_BASE_BVR + core_num_brps;
+                       /* Override the watchpoint data with the step data. */
+                       addr = info->trigger & ~0x3;
+                       ctrl = encode_ctrl_reg(info->step_ctrl);
+               } else {
+                       ctrl_base = ARM_BASE_WCR;
+                       val_base = ARM_BASE_WVR;
+               }
+               slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
                max_slots = core_num_wrps;
        }
 
@@ -355,12 +374,11 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
                goto out;
        }
 
-setup:
        /* Setup the address register. */
-       write_wb_reg(val_base + i, info->address);
+       write_wb_reg(val_base + i, addr);
 
        /* Setup the control register. */
-       write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1);
+       write_wb_reg(ctrl_base + i, ctrl);
 
 out:
        return ret;
@@ -375,18 +393,15 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
        if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
                /* Breakpoint */
                base = ARM_BASE_BCR;
-               slots = __get_cpu_var(bp_on_reg);
-               max_slots = core_num_brps - 1;
-
-               if (bp_is_single_step(bp)) {
-                       i = max_slots;
-                       slots[i] = NULL;
-                       goto reset;
-               }
+               slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
+               max_slots = core_num_brps;
        } else {
                /* Watchpoint */
-               base = ARM_BASE_WCR;
-               slots = __get_cpu_var(wp_on_reg);
+               if (info->step_ctrl.enabled)
+                       base = ARM_BASE_BCR + core_num_brps;
+               else
+                       base = ARM_BASE_WCR;
+               slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
                max_slots = core_num_wrps;
        }
 
@@ -403,7 +418,6 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
        if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
                return;
 
-reset:
        /* Reset the control register. */
        write_wb_reg(base + i, 0);
 }
@@ -537,12 +551,23 @@ static int arch_build_bp_info(struct perf_event *bp)
                return -EINVAL;
        }
 
+       /*
+        * Breakpoints must be of length 2 (thumb) or 4 (ARM) bytes.
+        * Watchpoints can be of length 1, 2, 4 or 8 bytes if supported
+        * by the hardware and must be aligned to the appropriate number of
+        * bytes.
+        */
+       if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE &&
+           info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
+           info->ctrl.len != ARM_BREAKPOINT_LEN_4)
+               return -EINVAL;
+
        /* Address */
        info->address = bp->attr.bp_addr;
 
        /* Privilege */
        info->ctrl.privilege = ARM_BREAKPOINT_USER;
-       if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp))
+       if (arch_check_bp_in_kernelspace(bp))
                info->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
 
        /* Enabled? */
@@ -561,7 +586,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 {
        struct arch_hw_breakpoint *info = counter_arch_bp(bp);
        int ret = 0;
-       u32 bytelen, max_len, offset, alignment_mask = 0x3;
+       u32 offset, alignment_mask = 0x3;
 
        /* Build the arch_hw_breakpoint. */
        ret = arch_build_bp_info(bp);
@@ -571,84 +596,85 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
        /* Check address alignment. */
        if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
                alignment_mask = 0x7;
-       if (info->address & alignment_mask) {
-               /*
-                * Try to fix the alignment. This may result in a length
-                * that is too large, so we must check for that.
-                */
-               bytelen = get_hbp_len(info->ctrl.len);
-               max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 :
-                               max_watchpoint_len;
-
-               if (max_len >= 8)
-                       offset = info->address & 0x7;
-               else
-                       offset = info->address & 0x3;
-
-               if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) {
-                       ret = -EFBIG;
-                       goto out;
-               }
-
-               info->ctrl.len <<= offset;
-               info->address &= ~offset;
-
-               pr_debug("breakpoint alignment fixup: length = 0x%x, "
-                       "address = 0x%x\n", info->ctrl.len, info->address);
+       offset = info->address & alignment_mask;
+       switch (offset) {
+       case 0:
+               /* Aligned */
+               break;
+       case 1:
+               /* Allow single byte watchpoint. */
+               if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
+                       break;
+       case 2:
+               /* Allow halfword watchpoints and breakpoints. */
+               if (info->ctrl.len == ARM_BREAKPOINT_LEN_2)
+                       break;
+       default:
+               ret = -EINVAL;
+               goto out;
        }
 
+       info->address &= ~alignment_mask;
+       info->ctrl.len <<= offset;
+
        /*
         * Currently we rely on an overflow handler to take
         * care of single-stepping the breakpoint when it fires.
         * In the case of userspace breakpoints on a core with V7 debug,
-        * we can use the mismatch feature as a poor-man's hardware single-step.
+        * we can use the mismatch feature as a poor-man's hardware
+        * single-step, but this only works for per-task breakpoints.
         */
        if (WARN_ONCE(!bp->overflow_handler &&
-               (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()),
+               (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
+                || !bp->hw.bp_target),
                        "overflow handler required but none found")) {
                ret = -EINVAL;
-               goto out;
        }
 out:
        return ret;
 }
 
-static void update_mismatch_flag(int idx, int flag)
+/*
+ * Enable/disable single-stepping over the breakpoint bp at address addr.
+ */
+static void enable_single_step(struct perf_event *bp, u32 addr)
 {
-       struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]);
-       struct arch_hw_breakpoint *info;
-
-       if (bp == NULL)
-               return;
+       struct arch_hw_breakpoint *info = counter_arch_bp(bp);
 
-       info = counter_arch_bp(bp);
+       arch_uninstall_hw_breakpoint(bp);
+       info->step_ctrl.mismatch  = 1;
+       info->step_ctrl.len       = ARM_BREAKPOINT_LEN_4;
+       info->step_ctrl.type      = ARM_BREAKPOINT_EXECUTE;
+       info->step_ctrl.privilege = info->ctrl.privilege;
+       info->step_ctrl.enabled   = 1;
+       info->trigger             = addr;
+       arch_install_hw_breakpoint(bp);
+}
 
-       /* Update the mismatch field to enter/exit `single-step' mode */
-       if (!bp->overflow_handler && info->ctrl.mismatch != flag) {
-               info->ctrl.mismatch = flag;
-               write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1);
-       }
+static void disable_single_step(struct perf_event *bp)
+{
+       arch_uninstall_hw_breakpoint(bp);
+       counter_arch_bp(bp)->step_ctrl.enabled = 0;
+       arch_install_hw_breakpoint(bp);
 }
 
 static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
 {
        int i;
-       struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg);
+       struct perf_event *wp, **slots;
        struct arch_hw_breakpoint *info;
-       struct perf_event_attr attr;
+
+       slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
 
        /* Without a disassembler, we can only handle 1 watchpoint. */
        BUG_ON(core_num_wrps > 1);
 
-       hw_breakpoint_init(&attr);
-       attr.bp_addr    = regs->ARM_pc & ~0x3;
-       attr.bp_len     = HW_BREAKPOINT_LEN_4;
-       attr.bp_type    = HW_BREAKPOINT_X;
-
        for (i = 0; i < core_num_wrps; ++i) {
                rcu_read_lock();
 
-               if (slots[i] == NULL) {
+               wp = slots[i];
+
+               if (wp == NULL) {
                        rcu_read_unlock();
                        continue;
                }
@@ -658,24 +684,51 @@ static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
                 * single watchpoint, we can set the trigger to the lowest
                 * possible faulting address.
                 */
-               info = counter_arch_bp(slots[i]);
-               info->trigger = slots[i]->attr.bp_addr;
+               info = counter_arch_bp(wp);
+               info->trigger = wp->attr.bp_addr;
                pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
-               perf_bp_event(slots[i], regs);
+               perf_bp_event(wp, regs);
 
                /*
                 * If no overflow handler is present, insert a temporary
                 * mismatch breakpoint so we can single-step over the
                 * watchpoint trigger.
                 */
-               if (!slots[i]->overflow_handler) {
-                       bp = register_user_hw_breakpoint(&attr,
-                                                        wp_single_step_handler,
-                                                        current);
-                       counter_arch_bp(bp)->suspended_wp = slots[i];
-                       perf_event_disable(slots[i]);
-               }
+               if (!wp->overflow_handler)
+                       enable_single_step(wp, instruction_pointer(regs));
+
+               rcu_read_unlock();
+       }
+}
 
+static void watchpoint_single_step_handler(unsigned long pc)
+{
+       int i;
+       struct perf_event *wp, **slots;
+       struct arch_hw_breakpoint *info;
+
+       slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
+
+       for (i = 0; i < core_num_reserved_brps; ++i) {
+               rcu_read_lock();
+
+               wp = slots[i];
+
+               if (wp == NULL)
+                       goto unlock;
+
+               info = counter_arch_bp(wp);
+               if (!info->step_ctrl.enabled)
+                       goto unlock;
+
+               /*
+                * Restore the original watchpoint if we've completed the
+                * single-step.
+                */
+               if (info->trigger != pc)
+                       disable_single_step(wp);
+
+unlock:
                rcu_read_unlock();
        }
 }
@@ -683,62 +736,69 @@ static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
 static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
 {
        int i;
-       int mismatch;
        u32 ctrl_reg, val, addr;
-       struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg);
+       struct perf_event *bp, **slots;
        struct arch_hw_breakpoint *info;
        struct arch_hw_breakpoint_ctrl ctrl;
 
+       slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
+
        /* The exception entry code places the amended lr in the PC. */
        addr = regs->ARM_pc;
 
+       /* Check the currently installed breakpoints first. */
        for (i = 0; i < core_num_brps; ++i) {
                rcu_read_lock();
 
                bp = slots[i];
 
-               if (bp == NULL) {
-                       rcu_read_unlock();
-                       continue;
-               }
+               if (bp == NULL)
+                       goto unlock;
 
-               mismatch = 0;
+               info = counter_arch_bp(bp);
 
                /* Check if the breakpoint value matches. */
                val = read_wb_reg(ARM_BASE_BVR + i);
                if (val != (addr & ~0x3))
-                       goto unlock;
+                       goto mismatch;
 
                /* Possible match, check the byte address select to confirm. */
                ctrl_reg = read_wb_reg(ARM_BASE_BCR + i);
                decode_ctrl_reg(ctrl_reg, &ctrl);
                if ((1 << (addr & 0x3)) & ctrl.len) {
-                       mismatch = 1;
-                       info = counter_arch_bp(bp);
                        info->trigger = addr;
-               }
-
-unlock:
-               if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) {
                        pr_debug("breakpoint fired: address = 0x%x\n", addr);
                        perf_bp_event(bp, regs);
+                       if (!bp->overflow_handler)
+                               enable_single_step(bp, addr);
+                       goto unlock;
                }
 
-               update_mismatch_flag(i, mismatch);
+mismatch:
+               /* If we're stepping a breakpoint, it can now be restored. */
+               if (info->step_ctrl.enabled)
+                       disable_single_step(bp);
+unlock:
                rcu_read_unlock();
        }
+
+       /* Handle any pending watchpoint single-step breakpoints. */
+       watchpoint_single_step_handler(addr);
 }
 
 /*
  * Called from either the Data Abort Handler [watchpoint] or the
- * Prefetch Abort Handler [breakpoint].
+ * Prefetch Abort Handler [breakpoint] with preemption disabled.
  */
 static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
                                 struct pt_regs *regs)
 {
-       int ret = 1; /* Unhandled fault. */
+       int ret = 0;
        u32 dscr;
 
+       /* We must be called with preemption disabled. */
+       WARN_ON(preemptible());
+
        /* We only handle watchpoints and hardware breakpoints. */
        ARM_DBG_READ(c1, 0, dscr);
 
@@ -753,25 +813,47 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
                watchpoint_handler(addr, regs);
                break;
        default:
-               goto out;
+               ret = 1; /* Unhandled fault. */
        }
 
-       ret = 0;
-out:
+       /*
+        * Re-enable preemption after it was disabled in the
+        * low-level exception handling code.
+        */
+       preempt_enable();
+
        return ret;
 }
 
 /*
  * One-time initialisation.
  */
-static void __init reset_ctrl_regs(void *unused)
+static void reset_ctrl_regs(void *unused)
 {
        int i;
 
+       /*
+        * v7 debug contains save and restore registers so that debug state
+        * can be maintained across low-power modes without leaving
+        * the debug logic powered up. It is IMPLEMENTATION DEFINED whether
+        * we can write to the debug registers out of reset, so we must
+        * unlock the OS Lock Access Register to avoid taking undefined
+        * instruction exceptions later on.
+        */
+       if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {
+               /*
+                * Unconditionally clear the lock by writing a value
+                * other than 0xC5ACCE55 to the access register.
+                */
+               asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
+               isb();
+       }
+
        if (enable_monitor_mode())
                return;
 
-       for (i = 0; i < core_num_brps; ++i) {
+       /* We must also reset any reserved registers. */
+       for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
                write_wb_reg(ARM_BASE_BCR + i, 0UL);
                write_wb_reg(ARM_BASE_BVR + i, 0UL);
        }
@@ -782,45 +864,57 @@ static void __init reset_ctrl_regs(void *unused)
        }
 }
 
+static int __cpuinit dbg_reset_notify(struct notifier_block *self,
+                                     unsigned long action, void *cpu)
+{
+       if (action == CPU_ONLINE)
+               smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata dbg_reset_nb = {
+       .notifier_call = dbg_reset_notify,
+};
+
 static int __init arch_hw_breakpoint_init(void)
 {
-       int ret = 0;
        u32 dscr;
 
        debug_arch = get_debug_arch();
 
        if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
                pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
-               ret = -ENODEV;
-               goto out;
+               return 0;
        }
 
        /* Determine how many BRPs/WRPs are available. */
        core_num_brps = get_num_brps();
+       core_num_reserved_brps = get_num_reserved_brps();
        core_num_wrps = get_num_wrps();
 
        pr_info("found %d breakpoint and %d watchpoint registers.\n",
-                       core_num_brps, core_num_wrps);
+               core_num_brps + core_num_reserved_brps, core_num_wrps);
 
-       if (core_has_mismatch_bps())
-               pr_info("1 breakpoint reserved for watchpoint single-step.\n");
+       if (core_num_reserved_brps)
+               pr_info("%d breakpoint(s) reserved for watchpoint "
+                               "single-step.\n", core_num_reserved_brps);
 
        ARM_DBG_READ(c1, 0, dscr);
        if (dscr & ARM_DSCR_HDBGEN) {
                pr_warning("halting debug mode enabled. Assuming maximum "
                                "watchpoint size of 4 bytes.");
        } else {
-               /* Work out the maximum supported watchpoint length. */
-               max_watchpoint_len = get_max_wp_len();
-               pr_info("maximum watchpoint size is %u bytes.\n",
-                               max_watchpoint_len);
-
                /*
                 * Reset the breakpoint resources. We assume that a halting
                 * debugger will leave the world in a nice state for us.
                 */
                smp_call_function(reset_ctrl_regs, NULL, 1);
                reset_ctrl_regs(NULL);
+
+               /* Work out the maximum supported watchpoint length. */
+               max_watchpoint_len = get_max_wp_len();
+               pr_info("maximum watchpoint size is %u bytes.\n",
+                               max_watchpoint_len);
        }
 
        /* Register debug fault handler. */
@@ -829,8 +923,9 @@ static int __init arch_hw_breakpoint_init(void)
        hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
                        "breakpoint debug exception");
 
-out:
-       return ret;
+       /* Register hotplug notifier. */
+       register_cpu_notifier(&dbg_reset_nb);
+       return 0;
 }
 arch_initcall(arch_hw_breakpoint_init);
 
index 36ad3be4692a21c4970de80b8d8562327571f681..6d616333340f1a97fdcaf1f8d591ac58c39da3bb 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
+#include <linux/ftrace.h>
 
 #include <asm/system.h>
 #include <asm/mach/irq.h>
@@ -105,7 +106,8 @@ unlock:
  * come via this function.  Instead, they should provide their
  * own 'handler'
  */
-asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+asmlinkage void __exception_irq_entry
+asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
index b63b528f22a693d4059680a98eb0d1a23182b1f2..7fa3bb0d2397a482989a6f82c6ab93ad674b59da 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
 
+#if defined(CONFIG_CPU_PJ4)
+#define PJ4(code...)           code
+#define XSC(code...)
+#else
+#define PJ4(code...)
+#define XSC(code...)           code
+#endif
+
 #define MMX_WR0                        (0x00)
 #define MMX_WR1                        (0x08)
 #define MMX_WR2                        (0x10)
 
 ENTRY(iwmmxt_task_enable)
 
-       mrc     p15, 0, r2, c15, c1, 0
-       tst     r2, #0x3                        @ CP0 and CP1 accessible?
+       XSC(mrc p15, 0, r2, c15, c1, 0)
+       PJ4(mrc p15, 0, r2, c1, c0, 2)
+       @ CP0 and CP1 accessible?
+       XSC(tst r2, #0x3)
+       PJ4(tst r2, #0xf)
        movne   pc, lr                          @ if so no business here
-       orr     r2, r2, #0x3                    @ enable access to CP0 and CP1
-       mcr     p15, 0, r2, c15, c1, 0
+       @ enable access to CP0 and CP1
+       XSC(orr r2, r2, #0x3)
+       XSC(mcr p15, 0, r2, c15, c1, 0)
+       PJ4(orr r2, r2, #0xf)
+       PJ4(mcr p15, 0, r2, c1, c0, 2)
 
        ldr     r3, =concan_owner
        add     r0, r10, #TI_IWMMXT_STATE       @ get task Concan save area
@@ -179,17 +193,26 @@ ENTRY(iwmmxt_task_disable)
        teqne   r1, r2                          @ or specified one?
        bne     1f                              @ no: quit
 
-       mrc     p15, 0, r4, c15, c1, 0
-       orr     r4, r4, #0x3                    @ enable access to CP0 and CP1
-       mcr     p15, 0, r4, c15, c1, 0
+       @ enable access to CP0 and CP1
+       XSC(mrc p15, 0, r4, c15, c1, 0)
+       XSC(orr r4, r4, #0xf)
+       XSC(mcr p15, 0, r4, c15, c1, 0)
+       PJ4(mrc p15, 0, r4, c1, c0, 2)
+       PJ4(orr r4, r4, #0x3)
+       PJ4(mcr p15, 0, r4, c1, c0, 2)
+
        mov     r0, #0                          @ nothing to load
        str     r0, [r3]                        @ no more current owner
        mrc     p15, 0, r2, c2, c0, 0
        mov     r2, r2                          @ cpwait
        bl      concan_save
 
-       bic     r4, r4, #0x3                    @ disable access to CP0 and CP1
-       mcr     p15, 0, r4, c15, c1, 0
+       @ disable access to CP0 and CP1
+       XSC(bic r4, r4, #0x3)
+       XSC(mcr p15, 0, r4, c15, c1, 0)
+       PJ4(bic r4, r4, #0xf)
+       PJ4(mcr p15, 0, r4, c1, c0, 2)
+
        mrc     p15, 0, r2, c2, c0, 0
        mov     r2, r2                          @ cpwait
 
@@ -277,8 +300,11 @@ ENTRY(iwmmxt_task_restore)
  */
 ENTRY(iwmmxt_task_switch)
 
-       mrc     p15, 0, r1, c15, c1, 0
-       tst     r1, #0x3                        @ CP0 and CP1 accessible?
+       XSC(mrc p15, 0, r1, c15, c1, 0)
+       PJ4(mrc p15, 0, r1, c1, c0, 2)
+       @ CP0 and CP1 accessible?
+       XSC(tst r1, #0x3)
+       PJ4(tst r1, #0xf)
        bne     1f                              @ yes: block them for next task
 
        ldr     r2, =concan_owner
@@ -287,8 +313,11 @@ ENTRY(iwmmxt_task_switch)
        teq     r2, r3                          @ next task owns it?
        movne   pc, lr                          @ no: leave Concan disabled
 
-1:     eor     r1, r1, #3                      @ flip Concan access
-       mcr     p15, 0, r1, c15, c1, 0
+1:     @ flip Conan access
+       XSC(eor r1, r1, #0x3)
+       XSC(mcr p15, 0, r1, c15, c1, 0)
+       PJ4(eor r1, r1, #0xf)
+       PJ4(mcr p15, 0, r1, c1, c0, 2)
 
        mrc     p15, 0, r1, c2, c0, 0
        sub     pc, lr, r1, lsr #32             @ cpwait and return
index 07a50357492ac6858bc21d0b7913aefc93cbb1cf..624e2a5de2b32ab681547de6455ed5f0517376bf 100644 (file)
@@ -4,9 +4,7 @@
  * ARM performance counter support.
  *
  * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
- *
- * ARMv7 support: Jean Pihet <jpihet@mvista.com>
- * 2010 (c) MontaVista Software, LLC.
+ * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
  *
  * This code is based on the sparc64 perf event code, which is in turn based
  * on the x86 code. Callchain code is based on the ARM OProfile backtrace
@@ -34,7 +32,7 @@ static struct platform_device *pmu_device;
  * Hardware lock to serialize accesses to PMU registers. Needed for the
  * read/modify/write sequences.
  */
-DEFINE_SPINLOCK(pmu_lock);
+static DEFINE_RAW_SPINLOCK(pmu_lock);
 
 /*
  * ARMv6 supports a maximum of 3 events, starting from index 1. If we add
@@ -67,31 +65,25 @@ struct cpu_hw_events {
         */
        unsigned long           active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)];
 };
-DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
-
-/* PMU names. */
-static const char *arm_pmu_names[] = {
-       [ARM_PERF_PMU_ID_XSCALE1] = "xscale1",
-       [ARM_PERF_PMU_ID_XSCALE2] = "xscale2",
-       [ARM_PERF_PMU_ID_V6]      = "v6",
-       [ARM_PERF_PMU_ID_V6MP]    = "v6mpcore",
-       [ARM_PERF_PMU_ID_CA8]     = "ARMv7 Cortex-A8",
-       [ARM_PERF_PMU_ID_CA9]     = "ARMv7 Cortex-A9",
-};
+static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
 
 struct arm_pmu {
        enum arm_perf_pmu_ids id;
+       const char      *name;
        irqreturn_t     (*handle_irq)(int irq_num, void *dev);
        void            (*enable)(struct hw_perf_event *evt, int idx);
        void            (*disable)(struct hw_perf_event *evt, int idx);
-       int             (*event_map)(int evt);
-       u64             (*raw_event)(u64);
        int             (*get_event_idx)(struct cpu_hw_events *cpuc,
                                         struct hw_perf_event *hwc);
        u32             (*read_counter)(int idx);
        void            (*write_counter)(int idx, u32 val);
        void            (*start)(void);
        void            (*stop)(void);
+       const unsigned  (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
+                                   [PERF_COUNT_HW_CACHE_OP_MAX]
+                                   [PERF_COUNT_HW_CACHE_RESULT_MAX];
+       const unsigned  (*event_map)[PERF_COUNT_HW_MAX];
+       u32             raw_event_mask;
        int             num_events;
        u64             max_period;
 };
@@ -136,10 +128,6 @@ EXPORT_SYMBOL_GPL(perf_num_counters);
 
 #define CACHE_OP_UNSUPPORTED           0xFFFF
 
-static unsigned armpmu_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-                                    [PERF_COUNT_HW_CACHE_OP_MAX]
-                                    [PERF_COUNT_HW_CACHE_RESULT_MAX];
-
 static int
 armpmu_map_cache_event(u64 config)
 {
@@ -157,7 +145,7 @@ armpmu_map_cache_event(u64 config)
        if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
                return -EINVAL;
 
-       ret = (int)armpmu_perf_cache_map[cache_type][cache_op][cache_result];
+       ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result];
 
        if (ret == CACHE_OP_UNSUPPORTED)
                return -ENOENT;
@@ -165,6 +153,19 @@ armpmu_map_cache_event(u64 config)
        return ret;
 }
 
+static int
+armpmu_map_event(u64 config)
+{
+       int mapping = (*armpmu->event_map)[config];
+       return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping;
+}
+
+static int
+armpmu_map_raw_event(u64 config)
+{
+       return (int)(config & armpmu->raw_event_mask);
+}
+
 static int
 armpmu_event_set_period(struct perf_event *event,
                        struct hw_perf_event *hwc,
@@ -458,11 +459,11 @@ __hw_perf_event_init(struct perf_event *event)
 
        /* Decode the generic type into an ARM event identifier. */
        if (PERF_TYPE_HARDWARE == event->attr.type) {
-               mapping = armpmu->event_map(event->attr.config);
+               mapping = armpmu_map_event(event->attr.config);
        } else if (PERF_TYPE_HW_CACHE == event->attr.type) {
                mapping = armpmu_map_cache_event(event->attr.config);
        } else if (PERF_TYPE_RAW == event->attr.type) {
-               mapping = armpmu->raw_event(event->attr.config);
+               mapping = armpmu_map_raw_event(event->attr.config);
        } else {
                pr_debug("event type %x not supported\n", event->attr.type);
                return -EOPNOTSUPP;
@@ -603,2366 +604,10 @@ static struct pmu pmu = {
        .read           = armpmu_read,
 };
 
-/*
- * ARMv6 Performance counter handling code.
- *
- * ARMv6 has 2 configurable performance counters and a single cycle counter.
- * They all share a single reset bit but can be written to zero so we can use
- * that for a reset.
- *
- * The counters can't be individually enabled or disabled so when we remove
- * one event and replace it with another we could get spurious counts from the
- * wrong event. However, we can take advantage of the fact that the
- * performance counters can export events to the event bus, and the event bus
- * itself can be monitored. This requires that we *don't* export the events to
- * the event bus. The procedure for disabling a configurable counter is:
- *     - change the counter to count the ETMEXTOUT[0] signal (0x20). This
- *       effectively stops the counter from counting.
- *     - disable the counter's interrupt generation (each counter has it's
- *       own interrupt enable bit).
- * Once stopped, the counter value can be written as 0 to reset.
- *
- * To enable a counter:
- *     - enable the counter's interrupt generation.
- *     - set the new event type.
- *
- * Note: the dedicated cycle counter only counts cycles and can't be
- * enabled/disabled independently of the others. When we want to disable the
- * cycle counter, we have to just disable the interrupt reporting and start
- * ignoring that counter. When re-enabling, we have to reset the value and
- * enable the interrupt.
- */
-
-enum armv6_perf_types {
-       ARMV6_PERFCTR_ICACHE_MISS           = 0x0,
-       ARMV6_PERFCTR_IBUF_STALL            = 0x1,
-       ARMV6_PERFCTR_DDEP_STALL            = 0x2,
-       ARMV6_PERFCTR_ITLB_MISS             = 0x3,
-       ARMV6_PERFCTR_DTLB_MISS             = 0x4,
-       ARMV6_PERFCTR_BR_EXEC               = 0x5,
-       ARMV6_PERFCTR_BR_MISPREDICT         = 0x6,
-       ARMV6_PERFCTR_INSTR_EXEC            = 0x7,
-       ARMV6_PERFCTR_DCACHE_HIT            = 0x9,
-       ARMV6_PERFCTR_DCACHE_ACCESS         = 0xA,
-       ARMV6_PERFCTR_DCACHE_MISS           = 0xB,
-       ARMV6_PERFCTR_DCACHE_WBACK          = 0xC,
-       ARMV6_PERFCTR_SW_PC_CHANGE          = 0xD,
-       ARMV6_PERFCTR_MAIN_TLB_MISS         = 0xF,
-       ARMV6_PERFCTR_EXPL_D_ACCESS         = 0x10,
-       ARMV6_PERFCTR_LSU_FULL_STALL        = 0x11,
-       ARMV6_PERFCTR_WBUF_DRAINED          = 0x12,
-       ARMV6_PERFCTR_CPU_CYCLES            = 0xFF,
-       ARMV6_PERFCTR_NOP                   = 0x20,
-};
-
-enum armv6_counters {
-       ARMV6_CYCLE_COUNTER = 1,
-       ARMV6_COUNTER0,
-       ARMV6_COUNTER1,
-};
-
-/*
- * The hardware events that we support. We do support cache operations but
- * we have harvard caches and no way to combine instruction and data
- * accesses/misses in hardware.
- */
-static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV6_PERFCTR_CPU_CYCLES,
-       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV6_PERFCTR_INSTR_EXEC,
-       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC,
-       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV6_PERFCTR_BR_MISPREDICT,
-       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
-};
-
-static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-                                         [PERF_COUNT_HW_CACHE_OP_MAX]
-                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-       [C(L1D)] = {
-               /*
-                * The performance counters don't differentiate between read
-                * and write accesses/misses so this isn't strictly correct,
-                * but it's the best we can do. Writes and reads get
-                * combined.
-                */
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = ARMV6_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DCACHE_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV6_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DCACHE_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(L1I)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ICACHE_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ICACHE_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(LL)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(DTLB)] = {
-               /*
-                * The ARM performance counters can count micro DTLB misses,
-                * micro ITLB misses and main TLB misses. There isn't an event
-                * for TLB misses, so use the micro misses here and if users
-                * want the main TLB misses they can use a raw counter.
-                */
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DTLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DTLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(ITLB)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(BPU)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-};
-
-enum armv6mpcore_perf_types {
-       ARMV6MPCORE_PERFCTR_ICACHE_MISS     = 0x0,
-       ARMV6MPCORE_PERFCTR_IBUF_STALL      = 0x1,
-       ARMV6MPCORE_PERFCTR_DDEP_STALL      = 0x2,
-       ARMV6MPCORE_PERFCTR_ITLB_MISS       = 0x3,
-       ARMV6MPCORE_PERFCTR_DTLB_MISS       = 0x4,
-       ARMV6MPCORE_PERFCTR_BR_EXEC         = 0x5,
-       ARMV6MPCORE_PERFCTR_BR_NOTPREDICT   = 0x6,
-       ARMV6MPCORE_PERFCTR_BR_MISPREDICT   = 0x7,
-       ARMV6MPCORE_PERFCTR_INSTR_EXEC      = 0x8,
-       ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS = 0xA,
-       ARMV6MPCORE_PERFCTR_DCACHE_RDMISS   = 0xB,
-       ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS = 0xC,
-       ARMV6MPCORE_PERFCTR_DCACHE_WRMISS   = 0xD,
-       ARMV6MPCORE_PERFCTR_DCACHE_EVICTION = 0xE,
-       ARMV6MPCORE_PERFCTR_SW_PC_CHANGE    = 0xF,
-       ARMV6MPCORE_PERFCTR_MAIN_TLB_MISS   = 0x10,
-       ARMV6MPCORE_PERFCTR_EXPL_MEM_ACCESS = 0x11,
-       ARMV6MPCORE_PERFCTR_LSU_FULL_STALL  = 0x12,
-       ARMV6MPCORE_PERFCTR_WBUF_DRAINED    = 0x13,
-       ARMV6MPCORE_PERFCTR_CPU_CYCLES      = 0xFF,
-};
-
-/*
- * The hardware events that we support. We do support cache operations but
- * we have harvard caches and no way to combine instruction and data
- * accesses/misses in hardware.
- */
-static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV6MPCORE_PERFCTR_CPU_CYCLES,
-       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV6MPCORE_PERFCTR_INSTR_EXEC,
-       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC,
-       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV6MPCORE_PERFCTR_BR_MISPREDICT,
-       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
-};
-
-static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-                                       [PERF_COUNT_HW_CACHE_OP_MAX]
-                                       [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-       [C(L1D)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]  =
-                               ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
-                       [C(RESULT_MISS)]    =
-                               ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]  =
-                               ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
-                       [C(RESULT_MISS)]    =
-                               ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(L1I)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(LL)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(DTLB)] = {
-               /*
-                * The ARM performance counters can count micro DTLB misses,
-                * micro ITLB misses and main TLB misses. There isn't an event
-                * for TLB misses, so use the micro misses here and if users
-                * want the main TLB misses they can use a raw counter.
-                */
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(ITLB)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(BPU)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
-               },
-       },
-};
-
-static inline unsigned long
-armv6_pmcr_read(void)
-{
-       u32 val;
-       asm volatile("mrc   p15, 0, %0, c15, c12, 0" : "=r"(val));
-       return val;
-}
-
-static inline void
-armv6_pmcr_write(unsigned long val)
-{
-       asm volatile("mcr   p15, 0, %0, c15, c12, 0" : : "r"(val));
-}
-
-#define ARMV6_PMCR_ENABLE              (1 << 0)
-#define ARMV6_PMCR_CTR01_RESET         (1 << 1)
-#define ARMV6_PMCR_CCOUNT_RESET                (1 << 2)
-#define ARMV6_PMCR_CCOUNT_DIV          (1 << 3)
-#define ARMV6_PMCR_COUNT0_IEN          (1 << 4)
-#define ARMV6_PMCR_COUNT1_IEN          (1 << 5)
-#define ARMV6_PMCR_CCOUNT_IEN          (1 << 6)
-#define ARMV6_PMCR_COUNT0_OVERFLOW     (1 << 8)
-#define ARMV6_PMCR_COUNT1_OVERFLOW     (1 << 9)
-#define ARMV6_PMCR_CCOUNT_OVERFLOW     (1 << 10)
-#define ARMV6_PMCR_EVT_COUNT0_SHIFT    20
-#define ARMV6_PMCR_EVT_COUNT0_MASK     (0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT)
-#define ARMV6_PMCR_EVT_COUNT1_SHIFT    12
-#define ARMV6_PMCR_EVT_COUNT1_MASK     (0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT)
-
-#define ARMV6_PMCR_OVERFLOWED_MASK \
-       (ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \
-        ARMV6_PMCR_CCOUNT_OVERFLOW)
-
-static inline int
-armv6_pmcr_has_overflowed(unsigned long pmcr)
-{
-       return (pmcr & ARMV6_PMCR_OVERFLOWED_MASK);
-}
-
-static inline int
-armv6_pmcr_counter_has_overflowed(unsigned long pmcr,
-                                 enum armv6_counters counter)
-{
-       int ret = 0;
-
-       if (ARMV6_CYCLE_COUNTER == counter)
-               ret = pmcr & ARMV6_PMCR_CCOUNT_OVERFLOW;
-       else if (ARMV6_COUNTER0 == counter)
-               ret = pmcr & ARMV6_PMCR_COUNT0_OVERFLOW;
-       else if (ARMV6_COUNTER1 == counter)
-               ret = pmcr & ARMV6_PMCR_COUNT1_OVERFLOW;
-       else
-               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-
-       return ret;
-}
-
-static inline u32
-armv6pmu_read_counter(int counter)
-{
-       unsigned long value = 0;
-
-       if (ARMV6_CYCLE_COUNTER == counter)
-               asm volatile("mrc   p15, 0, %0, c15, c12, 1" : "=r"(value));
-       else if (ARMV6_COUNTER0 == counter)
-               asm volatile("mrc   p15, 0, %0, c15, c12, 2" : "=r"(value));
-       else if (ARMV6_COUNTER1 == counter)
-               asm volatile("mrc   p15, 0, %0, c15, c12, 3" : "=r"(value));
-       else
-               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-
-       return value;
-}
-
-static inline void
-armv6pmu_write_counter(int counter,
-                      u32 value)
-{
-       if (ARMV6_CYCLE_COUNTER == counter)
-               asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value));
-       else if (ARMV6_COUNTER0 == counter)
-               asm volatile("mcr   p15, 0, %0, c15, c12, 2" : : "r"(value));
-       else if (ARMV6_COUNTER1 == counter)
-               asm volatile("mcr   p15, 0, %0, c15, c12, 3" : : "r"(value));
-       else
-               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-}
-
-void
-armv6pmu_enable_event(struct hw_perf_event *hwc,
-                     int idx)
-{
-       unsigned long val, mask, evt, flags;
-
-       if (ARMV6_CYCLE_COUNTER == idx) {
-               mask    = 0;
-               evt     = ARMV6_PMCR_CCOUNT_IEN;
-       } else if (ARMV6_COUNTER0 == idx) {
-               mask    = ARMV6_PMCR_EVT_COUNT0_MASK;
-               evt     = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) |
-                         ARMV6_PMCR_COUNT0_IEN;
-       } else if (ARMV6_COUNTER1 == idx) {
-               mask    = ARMV6_PMCR_EVT_COUNT1_MASK;
-               evt     = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) |
-                         ARMV6_PMCR_COUNT1_IEN;
-       } else {
-               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-               return;
-       }
-
-       /*
-        * Mask out the current event and set the counter to count the event
-        * that we're interested in.
-        */
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = armv6_pmcr_read();
-       val &= ~mask;
-       val |= evt;
-       armv6_pmcr_write(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static irqreturn_t
-armv6pmu_handle_irq(int irq_num,
-                   void *dev)
-{
-       unsigned long pmcr = armv6_pmcr_read();
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       struct pt_regs *regs;
-       int idx;
-
-       if (!armv6_pmcr_has_overflowed(pmcr))
-               return IRQ_NONE;
-
-       regs = get_irq_regs();
-
-       /*
-        * The interrupts are cleared by writing the overflow flags back to
-        * the control register. All of the other bits don't have any effect
-        * if they are rewritten, so write the whole value back.
-        */
-       armv6_pmcr_write(pmcr);
-
-       perf_sample_data_init(&data, 0);
-
-       cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
-               struct perf_event *event = cpuc->events[idx];
-               struct hw_perf_event *hwc;
-
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
-               /*
-                * We have a single interrupt for all counters. Check that
-                * each counter has overflowed before we process it.
-                */
-               if (!armv6_pmcr_counter_has_overflowed(pmcr, idx))
-                       continue;
-
-               hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
-               data.period = event->hw.last_period;
-               if (!armpmu_event_set_period(event, hwc, idx))
-                       continue;
-
-               if (perf_event_overflow(event, 0, &data, regs))
-                       armpmu->disable(hwc, idx);
-       }
-
-       /*
-        * Handle the pending perf events.
-        *
-        * Note: this call *must* be run with interrupts disabled. For
-        * platforms that can have the PMU interrupts raised as an NMI, this
-        * will not work.
-        */
-       irq_work_run();
-
-       return IRQ_HANDLED;
-}
-
-static void
-armv6pmu_start(void)
-{
-       unsigned long flags, val;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = armv6_pmcr_read();
-       val |= ARMV6_PMCR_ENABLE;
-       armv6_pmcr_write(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-void
-armv6pmu_stop(void)
-{
-       unsigned long flags, val;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = armv6_pmcr_read();
-       val &= ~ARMV6_PMCR_ENABLE;
-       armv6_pmcr_write(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline int
-armv6pmu_event_map(int config)
-{
-       int mapping = armv6_perf_map[config];
-       if (HW_OP_UNSUPPORTED == mapping)
-               mapping = -EOPNOTSUPP;
-       return mapping;
-}
-
-static inline int
-armv6mpcore_pmu_event_map(int config)
-{
-       int mapping = armv6mpcore_perf_map[config];
-       if (HW_OP_UNSUPPORTED == mapping)
-               mapping = -EOPNOTSUPP;
-       return mapping;
-}
-
-static u64
-armv6pmu_raw_event(u64 config)
-{
-       return config & 0xff;
-}
-
-static int
-armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
-                      struct hw_perf_event *event)
-{
-       /* Always place a cycle counter into the cycle counter. */
-       if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) {
-               if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask))
-                       return -EAGAIN;
-
-               return ARMV6_CYCLE_COUNTER;
-       } else {
-               /*
-                * For anything other than a cycle counter, try and use
-                * counter0 and counter1.
-                */
-               if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) {
-                       return ARMV6_COUNTER1;
-               }
-
-               if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) {
-                       return ARMV6_COUNTER0;
-               }
-
-               /* The counters are all in use. */
-               return -EAGAIN;
-       }
-}
-
-static void
-armv6pmu_disable_event(struct hw_perf_event *hwc,
-                      int idx)
-{
-       unsigned long val, mask, evt, flags;
-
-       if (ARMV6_CYCLE_COUNTER == idx) {
-               mask    = ARMV6_PMCR_CCOUNT_IEN;
-               evt     = 0;
-       } else if (ARMV6_COUNTER0 == idx) {
-               mask    = ARMV6_PMCR_COUNT0_IEN | ARMV6_PMCR_EVT_COUNT0_MASK;
-               evt     = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT0_SHIFT;
-       } else if (ARMV6_COUNTER1 == idx) {
-               mask    = ARMV6_PMCR_COUNT1_IEN | ARMV6_PMCR_EVT_COUNT1_MASK;
-               evt     = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT1_SHIFT;
-       } else {
-               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-               return;
-       }
-
-       /*
-        * Mask out the current event and set the counter to count the number
-        * of ETM bus signal assertion cycles. The external reporting should
-        * be disabled and so this should never increment.
-        */
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = armv6_pmcr_read();
-       val &= ~mask;
-       val |= evt;
-       armv6_pmcr_write(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
-                             int idx)
-{
-       unsigned long val, mask, flags, evt = 0;
-
-       if (ARMV6_CYCLE_COUNTER == idx) {
-               mask    = ARMV6_PMCR_CCOUNT_IEN;
-       } else if (ARMV6_COUNTER0 == idx) {
-               mask    = ARMV6_PMCR_COUNT0_IEN;
-       } else if (ARMV6_COUNTER1 == idx) {
-               mask    = ARMV6_PMCR_COUNT1_IEN;
-       } else {
-               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-               return;
-       }
-
-       /*
-        * Unlike UP ARMv6, we don't have a way of stopping the counters. We
-        * simply disable the interrupt reporting.
-        */
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = armv6_pmcr_read();
-       val &= ~mask;
-       val |= evt;
-       armv6_pmcr_write(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static const struct arm_pmu armv6pmu = {
-       .id                     = ARM_PERF_PMU_ID_V6,
-       .handle_irq             = armv6pmu_handle_irq,
-       .enable                 = armv6pmu_enable_event,
-       .disable                = armv6pmu_disable_event,
-       .event_map              = armv6pmu_event_map,
-       .raw_event              = armv6pmu_raw_event,
-       .read_counter           = armv6pmu_read_counter,
-       .write_counter          = armv6pmu_write_counter,
-       .get_event_idx          = armv6pmu_get_event_idx,
-       .start                  = armv6pmu_start,
-       .stop                   = armv6pmu_stop,
-       .num_events             = 3,
-       .max_period             = (1LLU << 32) - 1,
-};
-
-/*
- * ARMv6mpcore is almost identical to single core ARMv6 with the exception
- * that some of the events have different enumerations and that there is no
- * *hack* to stop the programmable counters. To stop the counters we simply
- * disable the interrupt reporting and update the event. When unthrottling we
- * reset the period and enable the interrupt reporting.
- */
-static const struct arm_pmu armv6mpcore_pmu = {
-       .id                     = ARM_PERF_PMU_ID_V6MP,
-       .handle_irq             = armv6pmu_handle_irq,
-       .enable                 = armv6pmu_enable_event,
-       .disable                = armv6mpcore_pmu_disable_event,
-       .event_map              = armv6mpcore_pmu_event_map,
-       .raw_event              = armv6pmu_raw_event,
-       .read_counter           = armv6pmu_read_counter,
-       .write_counter          = armv6pmu_write_counter,
-       .get_event_idx          = armv6pmu_get_event_idx,
-       .start                  = armv6pmu_start,
-       .stop                   = armv6pmu_stop,
-       .num_events             = 3,
-       .max_period             = (1LLU << 32) - 1,
-};
-
-/*
- * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code.
- *
- * Copied from ARMv6 code, with the low level code inspired
- *  by the ARMv7 Oprofile code.
- *
- * Cortex-A8 has up to 4 configurable performance counters and
- *  a single cycle counter.
- * Cortex-A9 has up to 31 configurable performance counters and
- *  a single cycle counter.
- *
- * All counters can be enabled/disabled and IRQ masked separately. The cycle
- *  counter and all 4 performance counters together can be reset separately.
- */
-
-/* Common ARMv7 event types */
-enum armv7_perf_types {
-       ARMV7_PERFCTR_PMNC_SW_INCR              = 0x00,
-       ARMV7_PERFCTR_IFETCH_MISS               = 0x01,
-       ARMV7_PERFCTR_ITLB_MISS                 = 0x02,
-       ARMV7_PERFCTR_DCACHE_REFILL             = 0x03,
-       ARMV7_PERFCTR_DCACHE_ACCESS             = 0x04,
-       ARMV7_PERFCTR_DTLB_REFILL               = 0x05,
-       ARMV7_PERFCTR_DREAD                     = 0x06,
-       ARMV7_PERFCTR_DWRITE                    = 0x07,
-
-       ARMV7_PERFCTR_EXC_TAKEN                 = 0x09,
-       ARMV7_PERFCTR_EXC_EXECUTED              = 0x0A,
-       ARMV7_PERFCTR_CID_WRITE                 = 0x0B,
-       /* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS.
-        * It counts:
-        *  - all branch instructions,
-        *  - instructions that explicitly write the PC,
-        *  - exception generating instructions.
-        */
-       ARMV7_PERFCTR_PC_WRITE                  = 0x0C,
-       ARMV7_PERFCTR_PC_IMM_BRANCH             = 0x0D,
-       ARMV7_PERFCTR_UNALIGNED_ACCESS          = 0x0F,
-       ARMV7_PERFCTR_PC_BRANCH_MIS_PRED        = 0x10,
-       ARMV7_PERFCTR_CLOCK_CYCLES              = 0x11,
-
-       ARMV7_PERFCTR_PC_BRANCH_MIS_USED        = 0x12,
-
-       ARMV7_PERFCTR_CPU_CYCLES                = 0xFF
-};
-
-/* ARMv7 Cortex-A8 specific event types */
-enum armv7_a8_perf_types {
-       ARMV7_PERFCTR_INSTR_EXECUTED            = 0x08,
-
-       ARMV7_PERFCTR_PC_PROC_RETURN            = 0x0E,
-
-       ARMV7_PERFCTR_WRITE_BUFFER_FULL         = 0x40,
-       ARMV7_PERFCTR_L2_STORE_MERGED           = 0x41,
-       ARMV7_PERFCTR_L2_STORE_BUFF             = 0x42,
-       ARMV7_PERFCTR_L2_ACCESS                 = 0x43,
-       ARMV7_PERFCTR_L2_CACH_MISS              = 0x44,
-       ARMV7_PERFCTR_AXI_READ_CYCLES           = 0x45,
-       ARMV7_PERFCTR_AXI_WRITE_CYCLES          = 0x46,
-       ARMV7_PERFCTR_MEMORY_REPLAY             = 0x47,
-       ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY   = 0x48,
-       ARMV7_PERFCTR_L1_DATA_MISS              = 0x49,
-       ARMV7_PERFCTR_L1_INST_MISS              = 0x4A,
-       ARMV7_PERFCTR_L1_DATA_COLORING          = 0x4B,
-       ARMV7_PERFCTR_L1_NEON_DATA              = 0x4C,
-       ARMV7_PERFCTR_L1_NEON_CACH_DATA         = 0x4D,
-       ARMV7_PERFCTR_L2_NEON                   = 0x4E,
-       ARMV7_PERFCTR_L2_NEON_HIT               = 0x4F,
-       ARMV7_PERFCTR_L1_INST                   = 0x50,
-       ARMV7_PERFCTR_PC_RETURN_MIS_PRED        = 0x51,
-       ARMV7_PERFCTR_PC_BRANCH_FAILED          = 0x52,
-       ARMV7_PERFCTR_PC_BRANCH_TAKEN           = 0x53,
-       ARMV7_PERFCTR_PC_BRANCH_EXECUTED        = 0x54,
-       ARMV7_PERFCTR_OP_EXECUTED               = 0x55,
-       ARMV7_PERFCTR_CYCLES_INST_STALL         = 0x56,
-       ARMV7_PERFCTR_CYCLES_INST               = 0x57,
-       ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL    = 0x58,
-       ARMV7_PERFCTR_CYCLES_NEON_INST_STALL    = 0x59,
-       ARMV7_PERFCTR_NEON_CYCLES               = 0x5A,
-
-       ARMV7_PERFCTR_PMU0_EVENTS               = 0x70,
-       ARMV7_PERFCTR_PMU1_EVENTS               = 0x71,
-       ARMV7_PERFCTR_PMU_EVENTS                = 0x72,
-};
-
-/* ARMv7 Cortex-A9 specific event types */
-enum armv7_a9_perf_types {
-       ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC     = 0x40,
-       ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC     = 0x41,
-       ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC       = 0x42,
-
-       ARMV7_PERFCTR_COHERENT_LINE_MISS        = 0x50,
-       ARMV7_PERFCTR_COHERENT_LINE_HIT         = 0x51,
-
-       ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES   = 0x60,
-       ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES   = 0x61,
-       ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES = 0x62,
-       ARMV7_PERFCTR_STREX_EXECUTED_PASSED     = 0x63,
-       ARMV7_PERFCTR_STREX_EXECUTED_FAILED     = 0x64,
-       ARMV7_PERFCTR_DATA_EVICTION             = 0x65,
-       ARMV7_PERFCTR_ISSUE_STAGE_NO_INST       = 0x66,
-       ARMV7_PERFCTR_ISSUE_STAGE_EMPTY         = 0x67,
-       ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE  = 0x68,
-
-       ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS = 0x6E,
-
-       ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST   = 0x70,
-       ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST = 0x71,
-       ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST  = 0x72,
-       ARMV7_PERFCTR_FP_EXECUTED_INST          = 0x73,
-       ARMV7_PERFCTR_NEON_EXECUTED_INST        = 0x74,
-
-       ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES = 0x80,
-       ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES  = 0x81,
-       ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES        = 0x82,
-       ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES        = 0x83,
-       ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES  = 0x84,
-       ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES  = 0x85,
-       ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES      = 0x86,
-
-       ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES  = 0x8A,
-       ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES = 0x8B,
-
-       ARMV7_PERFCTR_ISB_INST                  = 0x90,
-       ARMV7_PERFCTR_DSB_INST                  = 0x91,
-       ARMV7_PERFCTR_DMB_INST                  = 0x92,
-       ARMV7_PERFCTR_EXT_INTERRUPTS            = 0x93,
-
-       ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED     = 0xA0,
-       ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED       = 0xA1,
-       ARMV7_PERFCTR_PLE_FIFO_FLUSH            = 0xA2,
-       ARMV7_PERFCTR_PLE_RQST_COMPLETED        = 0xA3,
-       ARMV7_PERFCTR_PLE_FIFO_OVERFLOW         = 0xA4,
-       ARMV7_PERFCTR_PLE_RQST_PROG             = 0xA5
-};
-
-/*
- * Cortex-A8 HW events mapping
- *
- * The hardware events that we support. We do support cache operations but
- * we have harvard caches and no way to combine instruction and data
- * accesses/misses in hardware.
- */
-static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
-       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV7_PERFCTR_INSTR_EXECUTED,
-       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
-       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-       [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
-};
-
-static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-                                         [PERF_COUNT_HW_CACHE_OP_MAX]
-                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-       [C(L1D)] = {
-               /*
-                * The performance counters don't differentiate between read
-                * and write accesses/misses so this isn't strictly correct,
-                * but it's the best we can do. Writes and reads get
-                * combined.
-                */
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(L1I)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(LL)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(DTLB)] = {
-               /*
-                * Only ITLB misses and DTLB refills are supported.
-                * If users want the DTLB refills misses a raw counter
-                * must be used.
-                */
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(ITLB)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(BPU)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
-                       [C(RESULT_MISS)]
-                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
-                       [C(RESULT_MISS)]
-                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-};
-
-/*
- * Cortex-A9 HW events mapping
- */
-static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
-       [PERF_COUNT_HW_INSTRUCTIONS]        =
-                                       ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
-       [PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT,
-       [PERF_COUNT_HW_CACHE_MISSES]        = ARMV7_PERFCTR_COHERENT_LINE_MISS,
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
-       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-       [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
-};
-
-static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-                                         [PERF_COUNT_HW_CACHE_OP_MAX]
-                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-       [C(L1D)] = {
-               /*
-                * The performance counters don't differentiate between read
-                * and write accesses/misses so this isn't strictly correct,
-                * but it's the best we can do. Writes and reads get
-                * combined.
-                */
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(L1I)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(LL)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(DTLB)] = {
-               /*
-                * Only ITLB misses and DTLB refills are supported.
-                * If users want the DTLB refills misses a raw counter
-                * must be used.
-                */
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(ITLB)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(BPU)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
-                       [C(RESULT_MISS)]
-                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
-                       [C(RESULT_MISS)]
-                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-};
-
-/*
- * Perf Events counters
- */
-enum armv7_counters {
-       ARMV7_CYCLE_COUNTER             = 1,    /* Cycle counter */
-       ARMV7_COUNTER0                  = 2,    /* First event counter */
-};
-
-/*
- * The cycle counter is ARMV7_CYCLE_COUNTER.
- * The first event counter is ARMV7_COUNTER0.
- * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
- */
-#define        ARMV7_COUNTER_LAST      (ARMV7_COUNTER0 + armpmu->num_events - 1)
-
-/*
- * ARMv7 low level PMNC access
- */
-
-/*
- * Per-CPU PMNC: config reg
- */
-#define ARMV7_PMNC_E           (1 << 0) /* Enable all counters */
-#define ARMV7_PMNC_P           (1 << 1) /* Reset all counters */
-#define ARMV7_PMNC_C           (1 << 2) /* Cycle counter reset */
-#define ARMV7_PMNC_D           (1 << 3) /* CCNT counts every 64th cpu cycle */
-#define ARMV7_PMNC_X           (1 << 4) /* Export to ETM */
-#define ARMV7_PMNC_DP          (1 << 5) /* Disable CCNT if non-invasive debug*/
-#define        ARMV7_PMNC_N_SHIFT      11       /* Number of counters supported */
-#define        ARMV7_PMNC_N_MASK       0x1f
-#define        ARMV7_PMNC_MASK         0x3f     /* Mask for writable bits */
-
-/*
- * Available counters
- */
-#define ARMV7_CNT0             0       /* First event counter */
-#define ARMV7_CCNT             31      /* Cycle counter */
-
-/* Perf Event to low level counters mapping */
-#define ARMV7_EVENT_CNT_TO_CNTx        (ARMV7_COUNTER0 - ARMV7_CNT0)
-
-/*
- * CNTENS: counters enable reg
- */
-#define ARMV7_CNTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENS_C         (1 << ARMV7_CCNT)
-
-/*
- * CNTENC: counters disable reg
- */
-#define ARMV7_CNTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_CNTENC_C         (1 << ARMV7_CCNT)
-
-/*
- * INTENS: counters overflow interrupt enable reg
- */
-#define ARMV7_INTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENS_C         (1 << ARMV7_CCNT)
-
-/*
- * INTENC: counters overflow interrupt disable reg
- */
-#define ARMV7_INTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_INTENC_C         (1 << ARMV7_CCNT)
-
-/*
- * EVTSEL: Event selection reg
- */
-#define        ARMV7_EVTSEL_MASK       0xff            /* Mask for writable bits */
-
-/*
- * SELECT: Counter selection reg
- */
-#define        ARMV7_SELECT_MASK       0x1f            /* Mask for writable bits */
-
-/*
- * FLAG: counters overflow flag status reg
- */
-#define ARMV7_FLAG_P(idx)      (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
-#define ARMV7_FLAG_C           (1 << ARMV7_CCNT)
-#define        ARMV7_FLAG_MASK         0xffffffff      /* Mask for writable bits */
-#define        ARMV7_OVERFLOWED_MASK   ARMV7_FLAG_MASK
-
-static inline unsigned long armv7_pmnc_read(void)
-{
-       u32 val;
-       asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
-       return val;
-}
-
-static inline void armv7_pmnc_write(unsigned long val)
-{
-       val &= ARMV7_PMNC_MASK;
-       asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
-}
-
-static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
-{
-       return pmnc & ARMV7_OVERFLOWED_MASK;
-}
-
-static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
-                                       enum armv7_counters counter)
-{
-       int ret = 0;
-
-       if (counter == ARMV7_CYCLE_COUNTER)
-               ret = pmnc & ARMV7_FLAG_C;
-       else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
-               ret = pmnc & ARMV7_FLAG_P(counter);
-       else
-               pr_err("CPU%u checking wrong counter %d overflow status\n",
-                       smp_processor_id(), counter);
-
-       return ret;
-}
-
-static inline int armv7_pmnc_select_counter(unsigned int idx)
-{
-       u32 val;
-
-       if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
-               pr_err("CPU%u selecting wrong PMNC counter"
-                       " %d\n", smp_processor_id(), idx);
-               return -1;
-       }
-
-       val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
-       asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
-
-       return idx;
-}
-
-static inline u32 armv7pmu_read_counter(int idx)
-{
-       unsigned long value = 0;
-
-       if (idx == ARMV7_CYCLE_COUNTER)
-               asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
-       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-               if (armv7_pmnc_select_counter(idx) == idx)
-                       asm volatile("mrc p15, 0, %0, c9, c13, 2"
-                                    : "=r" (value));
-       } else
-               pr_err("CPU%u reading wrong counter %d\n",
-                       smp_processor_id(), idx);
-
-       return value;
-}
-
-static inline void armv7pmu_write_counter(int idx, u32 value)
-{
-       if (idx == ARMV7_CYCLE_COUNTER)
-               asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
-       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
-               if (armv7_pmnc_select_counter(idx) == idx)
-                       asm volatile("mcr p15, 0, %0, c9, c13, 2"
-                                    : : "r" (value));
-       } else
-               pr_err("CPU%u writing wrong counter %d\n",
-                       smp_processor_id(), idx);
-}
-
-static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
-{
-       if (armv7_pmnc_select_counter(idx) == idx) {
-               val &= ARMV7_EVTSEL_MASK;
-               asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
-       }
-}
-
-static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
-{
-       u32 val;
-
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u enabling wrong PMNC counter"
-                       " %d\n", smp_processor_id(), idx);
-               return -1;
-       }
-
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_CNTENS_C;
-       else
-               val = ARMV7_CNTENS_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
-
-       return idx;
-}
-
-static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
-{
-       u32 val;
-
-
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u disabling wrong PMNC counter"
-                       " %d\n", smp_processor_id(), idx);
-               return -1;
-       }
-
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_CNTENC_C;
-       else
-               val = ARMV7_CNTENC_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
-
-       return idx;
-}
-
-static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
-{
-       u32 val;
-
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u enabling wrong PMNC counter"
-                       " interrupt enable %d\n", smp_processor_id(), idx);
-               return -1;
-       }
-
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_INTENS_C;
-       else
-               val = ARMV7_INTENS_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
-
-       return idx;
-}
-
-static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
-{
-       u32 val;
-
-       if ((idx != ARMV7_CYCLE_COUNTER) &&
-           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
-               pr_err("CPU%u disabling wrong PMNC counter"
-                       " interrupt enable %d\n", smp_processor_id(), idx);
-               return -1;
-       }
-
-       if (idx == ARMV7_CYCLE_COUNTER)
-               val = ARMV7_INTENC_C;
-       else
-               val = ARMV7_INTENC_P(idx);
-
-       asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
-
-       return idx;
-}
-
-static inline u32 armv7_pmnc_getreset_flags(void)
-{
-       u32 val;
-
-       /* Read */
-       asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
-
-       /* Write to clear flags */
-       val &= ARMV7_FLAG_MASK;
-       asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
-
-       return val;
-}
-
-#ifdef DEBUG
-static void armv7_pmnc_dump_regs(void)
-{
-       u32 val;
-       unsigned int cnt;
-
-       printk(KERN_INFO "PMNC registers dump:\n");
-
-       asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
-       printk(KERN_INFO "PMNC  =0x%08x\n", val);
-
-       asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
-       printk(KERN_INFO "CNTENS=0x%08x\n", val);
-
-       asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
-       printk(KERN_INFO "INTENS=0x%08x\n", val);
-
-       asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
-       printk(KERN_INFO "FLAGS =0x%08x\n", val);
-
-       asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
-       printk(KERN_INFO "SELECT=0x%08x\n", val);
-
-       asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
-       printk(KERN_INFO "CCNT  =0x%08x\n", val);
-
-       for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
-               armv7_pmnc_select_counter(cnt);
-               asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
-               printk(KERN_INFO "CNT[%d] count =0x%08x\n",
-                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
-               asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
-               printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
-                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
-       }
-}
-#endif
-
-void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
-{
-       unsigned long flags;
-
-       /*
-        * Enable counter and interrupt, and set the counter to count
-        * the event that we're interested in.
-        */
-       spin_lock_irqsave(&pmu_lock, flags);
-
-       /*
-        * Disable counter
-        */
-       armv7_pmnc_disable_counter(idx);
-
-       /*
-        * Set event (if destined for PMNx counters)
-        * We don't need to set the event if it's a cycle count
-        */
-       if (idx != ARMV7_CYCLE_COUNTER)
-               armv7_pmnc_write_evtsel(idx, hwc->config_base);
-
-       /*
-        * Enable interrupt for this counter
-        */
-       armv7_pmnc_enable_intens(idx);
-
-       /*
-        * Enable counter
-        */
-       armv7_pmnc_enable_counter(idx);
-
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
-{
-       unsigned long flags;
-
-       /*
-        * Disable counter and interrupt
-        */
-       spin_lock_irqsave(&pmu_lock, flags);
-
-       /*
-        * Disable counter
-        */
-       armv7_pmnc_disable_counter(idx);
-
-       /*
-        * Disable interrupt for this counter
-        */
-       armv7_pmnc_disable_intens(idx);
-
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
-{
-       unsigned long pmnc;
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       struct pt_regs *regs;
-       int idx;
-
-       /*
-        * Get and reset the IRQ flags
-        */
-       pmnc = armv7_pmnc_getreset_flags();
-
-       /*
-        * Did an overflow occur?
-        */
-       if (!armv7_pmnc_has_overflowed(pmnc))
-               return IRQ_NONE;
-
-       /*
-        * Handle the counter(s) overflow(s)
-        */
-       regs = get_irq_regs();
-
-       perf_sample_data_init(&data, 0);
-
-       cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
-               struct perf_event *event = cpuc->events[idx];
-               struct hw_perf_event *hwc;
-
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
-               /*
-                * We have a single interrupt for all counters. Check that
-                * each counter has overflowed before we process it.
-                */
-               if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
-                       continue;
-
-               hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
-               data.period = event->hw.last_period;
-               if (!armpmu_event_set_period(event, hwc, idx))
-                       continue;
-
-               if (perf_event_overflow(event, 0, &data, regs))
-                       armpmu->disable(hwc, idx);
-       }
-
-       /*
-        * Handle the pending perf events.
-        *
-        * Note: this call *must* be run with interrupts disabled. For
-        * platforms that can have the PMU interrupts raised as an NMI, this
-        * will not work.
-        */
-       irq_work_run();
-
-       return IRQ_HANDLED;
-}
-
-static void armv7pmu_start(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       /* Enable all counters */
-       armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void armv7pmu_stop(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       /* Disable all counters */
-       armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline int armv7_a8_pmu_event_map(int config)
-{
-       int mapping = armv7_a8_perf_map[config];
-       if (HW_OP_UNSUPPORTED == mapping)
-               mapping = -EOPNOTSUPP;
-       return mapping;
-}
-
-static inline int armv7_a9_pmu_event_map(int config)
-{
-       int mapping = armv7_a9_perf_map[config];
-       if (HW_OP_UNSUPPORTED == mapping)
-               mapping = -EOPNOTSUPP;
-       return mapping;
-}
-
-static u64 armv7pmu_raw_event(u64 config)
-{
-       return config & 0xff;
-}
-
-static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
-                                 struct hw_perf_event *event)
-{
-       int idx;
-
-       /* Always place a cycle counter into the cycle counter. */
-       if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
-               if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
-                       return -EAGAIN;
-
-               return ARMV7_CYCLE_COUNTER;
-       } else {
-               /*
-                * For anything other than a cycle counter, try and use
-                * the events counters
-                */
-               for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
-                       if (!test_and_set_bit(idx, cpuc->used_mask))
-                               return idx;
-               }
-
-               /* The counters are all in use. */
-               return -EAGAIN;
-       }
-}
-
-static struct arm_pmu armv7pmu = {
-       .handle_irq             = armv7pmu_handle_irq,
-       .enable                 = armv7pmu_enable_event,
-       .disable                = armv7pmu_disable_event,
-       .raw_event              = armv7pmu_raw_event,
-       .read_counter           = armv7pmu_read_counter,
-       .write_counter          = armv7pmu_write_counter,
-       .get_event_idx          = armv7pmu_get_event_idx,
-       .start                  = armv7pmu_start,
-       .stop                   = armv7pmu_stop,
-       .max_period             = (1LLU << 32) - 1,
-};
-
-static u32 __init armv7_reset_read_pmnc(void)
-{
-       u32 nb_cnt;
-
-       /* Initialize & Reset PMNC: C and P bits */
-       armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
-
-       /* Read the nb of CNTx counters supported from PMNC */
-       nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
-
-       /* Add the CPU cycles counter and return */
-       return nb_cnt + 1;
-}
-
-/*
- * ARMv5 [xscale] Performance counter handling code.
- *
- * Based on xscale OProfile code.
- *
- * There are two variants of the xscale PMU that we support:
- *     - xscale1pmu: 2 event counters and a cycle counter
- *     - xscale2pmu: 4 event counters and a cycle counter
- * The two variants share event definitions, but have different
- * PMU structures.
- */
-
-enum xscale_perf_types {
-       XSCALE_PERFCTR_ICACHE_MISS              = 0x00,
-       XSCALE_PERFCTR_ICACHE_NO_DELIVER        = 0x01,
-       XSCALE_PERFCTR_DATA_STALL               = 0x02,
-       XSCALE_PERFCTR_ITLB_MISS                = 0x03,
-       XSCALE_PERFCTR_DTLB_MISS                = 0x04,
-       XSCALE_PERFCTR_BRANCH                   = 0x05,
-       XSCALE_PERFCTR_BRANCH_MISS              = 0x06,
-       XSCALE_PERFCTR_INSTRUCTION              = 0x07,
-       XSCALE_PERFCTR_DCACHE_FULL_STALL        = 0x08,
-       XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG = 0x09,
-       XSCALE_PERFCTR_DCACHE_ACCESS            = 0x0A,
-       XSCALE_PERFCTR_DCACHE_MISS              = 0x0B,
-       XSCALE_PERFCTR_DCACHE_WRITE_BACK        = 0x0C,
-       XSCALE_PERFCTR_PC_CHANGED               = 0x0D,
-       XSCALE_PERFCTR_BCU_REQUEST              = 0x10,
-       XSCALE_PERFCTR_BCU_FULL                 = 0x11,
-       XSCALE_PERFCTR_BCU_DRAIN                = 0x12,
-       XSCALE_PERFCTR_BCU_ECC_NO_ELOG          = 0x14,
-       XSCALE_PERFCTR_BCU_1_BIT_ERR            = 0x15,
-       XSCALE_PERFCTR_RMW                      = 0x16,
-       /* XSCALE_PERFCTR_CCNT is not hardware defined */
-       XSCALE_PERFCTR_CCNT                     = 0xFE,
-       XSCALE_PERFCTR_UNUSED                   = 0xFF,
-};
-
-enum xscale_counters {
-       XSCALE_CYCLE_COUNTER    = 1,
-       XSCALE_COUNTER0,
-       XSCALE_COUNTER1,
-       XSCALE_COUNTER2,
-       XSCALE_COUNTER3,
-};
-
-static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]          = XSCALE_PERFCTR_CCNT,
-       [PERF_COUNT_HW_INSTRUCTIONS]        = XSCALE_PERFCTR_INSTRUCTION,
-       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
-       [PERF_COUNT_HW_BRANCH_MISSES]       = XSCALE_PERFCTR_BRANCH_MISS,
-       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
-};
-
-static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
-                                          [PERF_COUNT_HW_CACHE_OP_MAX]
-                                          [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-       [C(L1D)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = XSCALE_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DCACHE_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = XSCALE_PERFCTR_DCACHE_ACCESS,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DCACHE_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(L1I)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ICACHE_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ICACHE_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(LL)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(DTLB)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DTLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DTLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(ITLB)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ITLB_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-       [C(BPU)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
-               },
-       },
-};
-
-#define        XSCALE_PMU_ENABLE       0x001
-#define XSCALE_PMN_RESET       0x002
-#define        XSCALE_CCNT_RESET       0x004
-#define        XSCALE_PMU_RESET        (CCNT_RESET | PMN_RESET)
-#define XSCALE_PMU_CNT64       0x008
-
-static inline int
-xscalepmu_event_map(int config)
-{
-       int mapping = xscale_perf_map[config];
-       if (HW_OP_UNSUPPORTED == mapping)
-               mapping = -EOPNOTSUPP;
-       return mapping;
-}
-
-static u64
-xscalepmu_raw_event(u64 config)
-{
-       return config & 0xff;
-}
-
-#define XSCALE1_OVERFLOWED_MASK        0x700
-#define XSCALE1_CCOUNT_OVERFLOW        0x400
-#define XSCALE1_COUNT0_OVERFLOW        0x100
-#define XSCALE1_COUNT1_OVERFLOW        0x200
-#define XSCALE1_CCOUNT_INT_EN  0x040
-#define XSCALE1_COUNT0_INT_EN  0x010
-#define XSCALE1_COUNT1_INT_EN  0x020
-#define XSCALE1_COUNT0_EVT_SHFT        12
-#define XSCALE1_COUNT0_EVT_MASK        (0xff << XSCALE1_COUNT0_EVT_SHFT)
-#define XSCALE1_COUNT1_EVT_SHFT        20
-#define XSCALE1_COUNT1_EVT_MASK        (0xff << XSCALE1_COUNT1_EVT_SHFT)
-
-static inline u32
-xscale1pmu_read_pmnc(void)
-{
-       u32 val;
-       asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
-       return val;
-}
-
-static inline void
-xscale1pmu_write_pmnc(u32 val)
-{
-       /* upper 4bits and 7, 11 are write-as-0 */
-       val &= 0xffff77f;
-       asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
-}
-
-static inline int
-xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
-                                       enum xscale_counters counter)
-{
-       int ret = 0;
-
-       switch (counter) {
-       case XSCALE_CYCLE_COUNTER:
-               ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
-               break;
-       case XSCALE_COUNTER0:
-               ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
-               break;
-       case XSCALE_COUNTER1:
-               ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
-               break;
-       default:
-               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-       }
-
-       return ret;
-}
-
-static irqreturn_t
-xscale1pmu_handle_irq(int irq_num, void *dev)
-{
-       unsigned long pmnc;
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       struct pt_regs *regs;
-       int idx;
-
-       /*
-        * NOTE: there's an A stepping erratum that states if an overflow
-        *       bit already exists and another occurs, the previous
-        *       Overflow bit gets cleared. There's no workaround.
-        *       Fixed in B stepping or later.
-        */
-       pmnc = xscale1pmu_read_pmnc();
-
-       /*
-        * Write the value back to clear the overflow flags. Overflow
-        * flags remain in pmnc for use below. We also disable the PMU
-        * while we process the interrupt.
-        */
-       xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
-
-       if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
-               return IRQ_NONE;
-
-       regs = get_irq_regs();
-
-       perf_sample_data_init(&data, 0);
-
-       cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
-               struct perf_event *event = cpuc->events[idx];
-               struct hw_perf_event *hwc;
-
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
-               if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
-                       continue;
-
-               hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
-               data.period = event->hw.last_period;
-               if (!armpmu_event_set_period(event, hwc, idx))
-                       continue;
-
-               if (perf_event_overflow(event, 0, &data, regs))
-                       armpmu->disable(hwc, idx);
-       }
-
-       irq_work_run();
-
-       /*
-        * Re-enable the PMU.
-        */
-       pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
-       xscale1pmu_write_pmnc(pmnc);
-
-       return IRQ_HANDLED;
-}
-
-static void
-xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
-{
-       unsigned long val, mask, evt, flags;
-
-       switch (idx) {
-       case XSCALE_CYCLE_COUNTER:
-               mask = 0;
-               evt = XSCALE1_CCOUNT_INT_EN;
-               break;
-       case XSCALE_COUNTER0:
-               mask = XSCALE1_COUNT0_EVT_MASK;
-               evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
-                       XSCALE1_COUNT0_INT_EN;
-               break;
-       case XSCALE_COUNTER1:
-               mask = XSCALE1_COUNT1_EVT_MASK;
-               evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
-                       XSCALE1_COUNT1_INT_EN;
-               break;
-       default:
-               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-               return;
-       }
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = xscale1pmu_read_pmnc();
-       val &= ~mask;
-       val |= evt;
-       xscale1pmu_write_pmnc(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
-{
-       unsigned long val, mask, evt, flags;
-
-       switch (idx) {
-       case XSCALE_CYCLE_COUNTER:
-               mask = XSCALE1_CCOUNT_INT_EN;
-               evt = 0;
-               break;
-       case XSCALE_COUNTER0:
-               mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
-               evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
-               break;
-       case XSCALE_COUNTER1:
-               mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
-               evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
-               break;
-       default:
-               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-               return;
-       }
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = xscale1pmu_read_pmnc();
-       val &= ~mask;
-       val |= evt;
-       xscale1pmu_write_pmnc(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static int
-xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
-                       struct hw_perf_event *event)
-{
-       if (XSCALE_PERFCTR_CCNT == event->config_base) {
-               if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
-                       return -EAGAIN;
-
-               return XSCALE_CYCLE_COUNTER;
-       } else {
-               if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask)) {
-                       return XSCALE_COUNTER1;
-               }
-
-               if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask)) {
-                       return XSCALE_COUNTER0;
-               }
-
-               return -EAGAIN;
-       }
-}
-
-static void
-xscale1pmu_start(void)
-{
-       unsigned long flags, val;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = xscale1pmu_read_pmnc();
-       val |= XSCALE_PMU_ENABLE;
-       xscale1pmu_write_pmnc(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale1pmu_stop(void)
-{
-       unsigned long flags, val;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = xscale1pmu_read_pmnc();
-       val &= ~XSCALE_PMU_ENABLE;
-       xscale1pmu_write_pmnc(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline u32
-xscale1pmu_read_counter(int counter)
-{
-       u32 val = 0;
-
-       switch (counter) {
-       case XSCALE_CYCLE_COUNTER:
-               asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
-               break;
-       case XSCALE_COUNTER0:
-               asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
-               break;
-       case XSCALE_COUNTER1:
-               asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
-               break;
-       }
-
-       return val;
-}
-
-static inline void
-xscale1pmu_write_counter(int counter, u32 val)
-{
-       switch (counter) {
-       case XSCALE_CYCLE_COUNTER:
-               asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
-               break;
-       case XSCALE_COUNTER0:
-               asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
-               break;
-       case XSCALE_COUNTER1:
-               asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
-               break;
-       }
-}
-
-static const struct arm_pmu xscale1pmu = {
-       .id             = ARM_PERF_PMU_ID_XSCALE1,
-       .handle_irq     = xscale1pmu_handle_irq,
-       .enable         = xscale1pmu_enable_event,
-       .disable        = xscale1pmu_disable_event,
-       .event_map      = xscalepmu_event_map,
-       .raw_event      = xscalepmu_raw_event,
-       .read_counter   = xscale1pmu_read_counter,
-       .write_counter  = xscale1pmu_write_counter,
-       .get_event_idx  = xscale1pmu_get_event_idx,
-       .start          = xscale1pmu_start,
-       .stop           = xscale1pmu_stop,
-       .num_events     = 3,
-       .max_period     = (1LLU << 32) - 1,
-};
-
-#define XSCALE2_OVERFLOWED_MASK        0x01f
-#define XSCALE2_CCOUNT_OVERFLOW        0x001
-#define XSCALE2_COUNT0_OVERFLOW        0x002
-#define XSCALE2_COUNT1_OVERFLOW        0x004
-#define XSCALE2_COUNT2_OVERFLOW        0x008
-#define XSCALE2_COUNT3_OVERFLOW        0x010
-#define XSCALE2_CCOUNT_INT_EN  0x001
-#define XSCALE2_COUNT0_INT_EN  0x002
-#define XSCALE2_COUNT1_INT_EN  0x004
-#define XSCALE2_COUNT2_INT_EN  0x008
-#define XSCALE2_COUNT3_INT_EN  0x010
-#define XSCALE2_COUNT0_EVT_SHFT        0
-#define XSCALE2_COUNT0_EVT_MASK        (0xff << XSCALE2_COUNT0_EVT_SHFT)
-#define XSCALE2_COUNT1_EVT_SHFT        8
-#define XSCALE2_COUNT1_EVT_MASK        (0xff << XSCALE2_COUNT1_EVT_SHFT)
-#define XSCALE2_COUNT2_EVT_SHFT        16
-#define XSCALE2_COUNT2_EVT_MASK        (0xff << XSCALE2_COUNT2_EVT_SHFT)
-#define XSCALE2_COUNT3_EVT_SHFT        24
-#define XSCALE2_COUNT3_EVT_MASK        (0xff << XSCALE2_COUNT3_EVT_SHFT)
-
-static inline u32
-xscale2pmu_read_pmnc(void)
-{
-       u32 val;
-       asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
-       /* bits 1-2 and 4-23 are read-unpredictable */
-       return val & 0xff000009;
-}
-
-static inline void
-xscale2pmu_write_pmnc(u32 val)
-{
-       /* bits 4-23 are write-as-0, 24-31 are write ignored */
-       val &= 0xf;
-       asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
-}
-
-static inline u32
-xscale2pmu_read_overflow_flags(void)
-{
-       u32 val;
-       asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
-       return val;
-}
-
-static inline void
-xscale2pmu_write_overflow_flags(u32 val)
-{
-       asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
-}
-
-static inline u32
-xscale2pmu_read_event_select(void)
-{
-       u32 val;
-       asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
-       return val;
-}
-
-static inline void
-xscale2pmu_write_event_select(u32 val)
-{
-       asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
-}
-
-static inline u32
-xscale2pmu_read_int_enable(void)
-{
-       u32 val;
-       asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
-       return val;
-}
-
-static void
-xscale2pmu_write_int_enable(u32 val)
-{
-       asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
-}
-
-static inline int
-xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
-                                       enum xscale_counters counter)
-{
-       int ret = 0;
-
-       switch (counter) {
-       case XSCALE_CYCLE_COUNTER:
-               ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
-               break;
-       case XSCALE_COUNTER0:
-               ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
-               break;
-       case XSCALE_COUNTER1:
-               ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
-               break;
-       case XSCALE_COUNTER2:
-               ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
-               break;
-       case XSCALE_COUNTER3:
-               ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
-               break;
-       default:
-               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
-       }
-
-       return ret;
-}
-
-static irqreturn_t
-xscale2pmu_handle_irq(int irq_num, void *dev)
-{
-       unsigned long pmnc, of_flags;
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       struct pt_regs *regs;
-       int idx;
-
-       /* Disable the PMU. */
-       pmnc = xscale2pmu_read_pmnc();
-       xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
-
-       /* Check the overflow flag register. */
-       of_flags = xscale2pmu_read_overflow_flags();
-       if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
-               return IRQ_NONE;
-
-       /* Clear the overflow bits. */
-       xscale2pmu_write_overflow_flags(of_flags);
-
-       regs = get_irq_regs();
-
-       perf_sample_data_init(&data, 0);
-
-       cpuc = &__get_cpu_var(cpu_hw_events);
-       for (idx = 0; idx <= armpmu->num_events; ++idx) {
-               struct perf_event *event = cpuc->events[idx];
-               struct hw_perf_event *hwc;
-
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
-               if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
-                       continue;
-
-               hwc = &event->hw;
-               armpmu_event_update(event, hwc, idx);
-               data.period = event->hw.last_period;
-               if (!armpmu_event_set_period(event, hwc, idx))
-                       continue;
-
-               if (perf_event_overflow(event, 0, &data, regs))
-                       armpmu->disable(hwc, idx);
-       }
-
-       irq_work_run();
-
-       /*
-        * Re-enable the PMU.
-        */
-       pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
-       xscale2pmu_write_pmnc(pmnc);
-
-       return IRQ_HANDLED;
-}
-
-static void
-xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
-{
-       unsigned long flags, ien, evtsel;
-
-       ien = xscale2pmu_read_int_enable();
-       evtsel = xscale2pmu_read_event_select();
-
-       switch (idx) {
-       case XSCALE_CYCLE_COUNTER:
-               ien |= XSCALE2_CCOUNT_INT_EN;
-               break;
-       case XSCALE_COUNTER0:
-               ien |= XSCALE2_COUNT0_INT_EN;
-               evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
-               evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
-               break;
-       case XSCALE_COUNTER1:
-               ien |= XSCALE2_COUNT1_INT_EN;
-               evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
-               evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
-               break;
-       case XSCALE_COUNTER2:
-               ien |= XSCALE2_COUNT2_INT_EN;
-               evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
-               evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
-               break;
-       case XSCALE_COUNTER3:
-               ien |= XSCALE2_COUNT3_INT_EN;
-               evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
-               evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
-               break;
-       default:
-               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-               return;
-       }
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       xscale2pmu_write_event_select(evtsel);
-       xscale2pmu_write_int_enable(ien);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
-{
-       unsigned long flags, ien, evtsel;
-
-       ien = xscale2pmu_read_int_enable();
-       evtsel = xscale2pmu_read_event_select();
-
-       switch (idx) {
-       case XSCALE_CYCLE_COUNTER:
-               ien &= ~XSCALE2_CCOUNT_INT_EN;
-               break;
-       case XSCALE_COUNTER0:
-               ien &= ~XSCALE2_COUNT0_INT_EN;
-               evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
-               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
-               break;
-       case XSCALE_COUNTER1:
-               ien &= ~XSCALE2_COUNT1_INT_EN;
-               evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
-               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
-               break;
-       case XSCALE_COUNTER2:
-               ien &= ~XSCALE2_COUNT2_INT_EN;
-               evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
-               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
-               break;
-       case XSCALE_COUNTER3:
-               ien &= ~XSCALE2_COUNT3_INT_EN;
-               evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
-               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
-               break;
-       default:
-               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
-               return;
-       }
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       xscale2pmu_write_event_select(evtsel);
-       xscale2pmu_write_int_enable(ien);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static int
-xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
-                       struct hw_perf_event *event)
-{
-       int idx = xscale1pmu_get_event_idx(cpuc, event);
-       if (idx >= 0)
-               goto out;
-
-       if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
-               idx = XSCALE_COUNTER3;
-       else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
-               idx = XSCALE_COUNTER2;
-out:
-       return idx;
-}
-
-static void
-xscale2pmu_start(void)
-{
-       unsigned long flags, val;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
-       val |= XSCALE_PMU_ENABLE;
-       xscale2pmu_write_pmnc(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static void
-xscale2pmu_stop(void)
-{
-       unsigned long flags, val;
-
-       spin_lock_irqsave(&pmu_lock, flags);
-       val = xscale2pmu_read_pmnc();
-       val &= ~XSCALE_PMU_ENABLE;
-       xscale2pmu_write_pmnc(val);
-       spin_unlock_irqrestore(&pmu_lock, flags);
-}
-
-static inline u32
-xscale2pmu_read_counter(int counter)
-{
-       u32 val = 0;
-
-       switch (counter) {
-       case XSCALE_CYCLE_COUNTER:
-               asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
-               break;
-       case XSCALE_COUNTER0:
-               asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
-               break;
-       case XSCALE_COUNTER1:
-               asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
-               break;
-       case XSCALE_COUNTER2:
-               asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
-               break;
-       case XSCALE_COUNTER3:
-               asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
-               break;
-       }
-
-       return val;
-}
-
-static inline void
-xscale2pmu_write_counter(int counter, u32 val)
-{
-       switch (counter) {
-       case XSCALE_CYCLE_COUNTER:
-               asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
-               break;
-       case XSCALE_COUNTER0:
-               asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
-               break;
-       case XSCALE_COUNTER1:
-               asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
-               break;
-       case XSCALE_COUNTER2:
-               asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
-               break;
-       case XSCALE_COUNTER3:
-               asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
-               break;
-       }
-}
-
-static const struct arm_pmu xscale2pmu = {
-       .id             = ARM_PERF_PMU_ID_XSCALE2,
-       .handle_irq     = xscale2pmu_handle_irq,
-       .enable         = xscale2pmu_enable_event,
-       .disable        = xscale2pmu_disable_event,
-       .event_map      = xscalepmu_event_map,
-       .raw_event      = xscalepmu_raw_event,
-       .read_counter   = xscale2pmu_read_counter,
-       .write_counter  = xscale2pmu_write_counter,
-       .get_event_idx  = xscale2pmu_get_event_idx,
-       .start          = xscale2pmu_start,
-       .stop           = xscale2pmu_stop,
-       .num_events     = 5,
-       .max_period     = (1LLU << 32) - 1,
-};
+/* Include the PMU-specific implementations. */
+#include "perf_event_xscale.c"
+#include "perf_event_v6.c"
+#include "perf_event_v7.c"
 
 static int __init
 init_hw_perf_events(void)
@@ -2977,37 +622,16 @@ init_hw_perf_events(void)
                case 0xB360:    /* ARM1136 */
                case 0xB560:    /* ARM1156 */
                case 0xB760:    /* ARM1176 */
-                       armpmu = &armv6pmu;
-                       memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
-                                       sizeof(armv6_perf_cache_map));
+                       armpmu = armv6pmu_init();
                        break;
                case 0xB020:    /* ARM11mpcore */
-                       armpmu = &armv6mpcore_pmu;
-                       memcpy(armpmu_perf_cache_map,
-                              armv6mpcore_perf_cache_map,
-                              sizeof(armv6mpcore_perf_cache_map));
+                       armpmu = armv6mpcore_pmu_init();
                        break;
                case 0xC080:    /* Cortex-A8 */
-                       armv7pmu.id = ARM_PERF_PMU_ID_CA8;
-                       memcpy(armpmu_perf_cache_map, armv7_a8_perf_cache_map,
-                               sizeof(armv7_a8_perf_cache_map));
-                       armv7pmu.event_map = armv7_a8_pmu_event_map;
-                       armpmu = &armv7pmu;
-
-                       /* Reset PMNC and read the nb of CNTx counters
-                           supported */
-                       armv7pmu.num_events = armv7_reset_read_pmnc();
+                       armpmu = armv7_a8_pmu_init();
                        break;
                case 0xC090:    /* Cortex-A9 */
-                       armv7pmu.id = ARM_PERF_PMU_ID_CA9;
-                       memcpy(armpmu_perf_cache_map, armv7_a9_perf_cache_map,
-                               sizeof(armv7_a9_perf_cache_map));
-                       armv7pmu.event_map = armv7_a9_pmu_event_map;
-                       armpmu = &armv7pmu;
-
-                       /* Reset PMNC and read the nb of CNTx counters
-                           supported */
-                       armv7pmu.num_events = armv7_reset_read_pmnc();
+                       armpmu = armv7_a9_pmu_init();
                        break;
                }
        /* Intel CPUs [xscale]. */
@@ -3015,21 +639,17 @@ init_hw_perf_events(void)
                part_number = (cpuid >> 13) & 0x7;
                switch (part_number) {
                case 1:
-                       armpmu = &xscale1pmu;
-                       memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
-                                       sizeof(xscale_perf_cache_map));
+                       armpmu = xscale1pmu_init();
                        break;
                case 2:
-                       armpmu = &xscale2pmu;
-                       memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
-                                       sizeof(xscale_perf_cache_map));
+                       armpmu = xscale2pmu_init();
                        break;
                }
        }
 
        if (armpmu) {
                pr_info("enabled with %s PMU driver, %d counters available\n",
-                               arm_pmu_names[armpmu->id], armpmu->num_events);
+                       armpmu->name, armpmu->num_events);
        } else {
                pr_info("no hardware support available\n");
        }
@@ -3053,17 +673,17 @@ arch_initcall(init_hw_perf_events);
  * This code has been adapted from the ARM OProfile support.
  */
 struct frame_tail {
-       struct frame_tail   *fp;
-       unsigned long       sp;
-       unsigned long       lr;
+       struct frame_tail __user *fp;
+       unsigned long sp;
+       unsigned long lr;
 } __attribute__((packed));
 
 /*
  * Get the return address for a single stackframe and return a pointer to the
  * next frame tail.
  */
-static struct frame_tail *
-user_backtrace(struct frame_tail *tail,
+static struct frame_tail __user *
+user_backtrace(struct frame_tail __user *tail,
               struct perf_callchain_entry *entry)
 {
        struct frame_tail buftail;
@@ -3089,10 +709,10 @@ user_backtrace(struct frame_tail *tail,
 void
 perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
-       struct frame_tail *tail;
+       struct frame_tail __user *tail;
 
 
-       tail = (struct frame_tail *)regs->ARM_fp - 1;
+       tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
        while (tail && !((unsigned long)tail & 0x3))
                tail = user_backtrace(tail, entry);
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
new file mode 100644 (file)
index 0000000..c058bfc
--- /dev/null
@@ -0,0 +1,672 @@
+/*
+ * ARMv6 Performance counter handling code.
+ *
+ * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
+ *
+ * ARMv6 has 2 configurable performance counters and a single cycle counter.
+ * They all share a single reset bit but can be written to zero so we can use
+ * that for a reset.
+ *
+ * The counters can't be individually enabled or disabled so when we remove
+ * one event and replace it with another we could get spurious counts from the
+ * wrong event. However, we can take advantage of the fact that the
+ * performance counters can export events to the event bus, and the event bus
+ * itself can be monitored. This requires that we *don't* export the events to
+ * the event bus. The procedure for disabling a configurable counter is:
+ *     - change the counter to count the ETMEXTOUT[0] signal (0x20). This
+ *       effectively stops the counter from counting.
+ *     - disable the counter's interrupt generation (each counter has it's
+ *       own interrupt enable bit).
+ * Once stopped, the counter value can be written as 0 to reset.
+ *
+ * To enable a counter:
+ *     - enable the counter's interrupt generation.
+ *     - set the new event type.
+ *
+ * Note: the dedicated cycle counter only counts cycles and can't be
+ * enabled/disabled independently of the others. When we want to disable the
+ * cycle counter, we have to just disable the interrupt reporting and start
+ * ignoring that counter. When re-enabling, we have to reset the value and
+ * enable the interrupt.
+ */
+
+#ifdef CONFIG_CPU_V6
+enum armv6_perf_types {
+       ARMV6_PERFCTR_ICACHE_MISS           = 0x0,
+       ARMV6_PERFCTR_IBUF_STALL            = 0x1,
+       ARMV6_PERFCTR_DDEP_STALL            = 0x2,
+       ARMV6_PERFCTR_ITLB_MISS             = 0x3,
+       ARMV6_PERFCTR_DTLB_MISS             = 0x4,
+       ARMV6_PERFCTR_BR_EXEC               = 0x5,
+       ARMV6_PERFCTR_BR_MISPREDICT         = 0x6,
+       ARMV6_PERFCTR_INSTR_EXEC            = 0x7,
+       ARMV6_PERFCTR_DCACHE_HIT            = 0x9,
+       ARMV6_PERFCTR_DCACHE_ACCESS         = 0xA,
+       ARMV6_PERFCTR_DCACHE_MISS           = 0xB,
+       ARMV6_PERFCTR_DCACHE_WBACK          = 0xC,
+       ARMV6_PERFCTR_SW_PC_CHANGE          = 0xD,
+       ARMV6_PERFCTR_MAIN_TLB_MISS         = 0xF,
+       ARMV6_PERFCTR_EXPL_D_ACCESS         = 0x10,
+       ARMV6_PERFCTR_LSU_FULL_STALL        = 0x11,
+       ARMV6_PERFCTR_WBUF_DRAINED          = 0x12,
+       ARMV6_PERFCTR_CPU_CYCLES            = 0xFF,
+       ARMV6_PERFCTR_NOP                   = 0x20,
+};
+
+enum armv6_counters {
+       ARMV6_CYCLE_COUNTER = 1,
+       ARMV6_COUNTER0,
+       ARMV6_COUNTER1,
+};
+
+/*
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV6_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV6_PERFCTR_INSTR_EXEC,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV6_PERFCTR_BR_MISPREDICT,
+       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                         [PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV6_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DCACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV6_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DCACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * The ARM performance counters can count micro DTLB misses,
+                * micro ITLB misses and main TLB misses. There isn't an event
+                * for TLB misses, so use the micro misses here and if users
+                * want the main TLB misses they can use a raw counter.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+enum armv6mpcore_perf_types {
+       ARMV6MPCORE_PERFCTR_ICACHE_MISS     = 0x0,
+       ARMV6MPCORE_PERFCTR_IBUF_STALL      = 0x1,
+       ARMV6MPCORE_PERFCTR_DDEP_STALL      = 0x2,
+       ARMV6MPCORE_PERFCTR_ITLB_MISS       = 0x3,
+       ARMV6MPCORE_PERFCTR_DTLB_MISS       = 0x4,
+       ARMV6MPCORE_PERFCTR_BR_EXEC         = 0x5,
+       ARMV6MPCORE_PERFCTR_BR_NOTPREDICT   = 0x6,
+       ARMV6MPCORE_PERFCTR_BR_MISPREDICT   = 0x7,
+       ARMV6MPCORE_PERFCTR_INSTR_EXEC      = 0x8,
+       ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS = 0xA,
+       ARMV6MPCORE_PERFCTR_DCACHE_RDMISS   = 0xB,
+       ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS = 0xC,
+       ARMV6MPCORE_PERFCTR_DCACHE_WRMISS   = 0xD,
+       ARMV6MPCORE_PERFCTR_DCACHE_EVICTION = 0xE,
+       ARMV6MPCORE_PERFCTR_SW_PC_CHANGE    = 0xF,
+       ARMV6MPCORE_PERFCTR_MAIN_TLB_MISS   = 0x10,
+       ARMV6MPCORE_PERFCTR_EXPL_MEM_ACCESS = 0x11,
+       ARMV6MPCORE_PERFCTR_LSU_FULL_STALL  = 0x12,
+       ARMV6MPCORE_PERFCTR_WBUF_DRAINED    = 0x13,
+       ARMV6MPCORE_PERFCTR_CPU_CYCLES      = 0xFF,
+};
+
+/*
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV6MPCORE_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV6MPCORE_PERFCTR_INSTR_EXEC,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV6MPCORE_PERFCTR_BR_MISPREDICT,
+       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                       [PERF_COUNT_HW_CACHE_OP_MAX]
+                                       [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  =
+                               ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
+                       [C(RESULT_MISS)]    =
+                               ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  =
+                               ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
+                       [C(RESULT_MISS)]    =
+                               ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * The ARM performance counters can count micro DTLB misses,
+                * micro ITLB misses and main TLB misses. There isn't an event
+                * for TLB misses, so use the micro misses here and if users
+                * want the main TLB misses they can use a raw counter.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+static inline unsigned long
+armv6_pmcr_read(void)
+{
+       u32 val;
+       asm volatile("mrc   p15, 0, %0, c15, c12, 0" : "=r"(val));
+       return val;
+}
+
+static inline void
+armv6_pmcr_write(unsigned long val)
+{
+       asm volatile("mcr   p15, 0, %0, c15, c12, 0" : : "r"(val));
+}
+
+#define ARMV6_PMCR_ENABLE              (1 << 0)
+#define ARMV6_PMCR_CTR01_RESET         (1 << 1)
+#define ARMV6_PMCR_CCOUNT_RESET                (1 << 2)
+#define ARMV6_PMCR_CCOUNT_DIV          (1 << 3)
+#define ARMV6_PMCR_COUNT0_IEN          (1 << 4)
+#define ARMV6_PMCR_COUNT1_IEN          (1 << 5)
+#define ARMV6_PMCR_CCOUNT_IEN          (1 << 6)
+#define ARMV6_PMCR_COUNT0_OVERFLOW     (1 << 8)
+#define ARMV6_PMCR_COUNT1_OVERFLOW     (1 << 9)
+#define ARMV6_PMCR_CCOUNT_OVERFLOW     (1 << 10)
+#define ARMV6_PMCR_EVT_COUNT0_SHIFT    20
+#define ARMV6_PMCR_EVT_COUNT0_MASK     (0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT)
+#define ARMV6_PMCR_EVT_COUNT1_SHIFT    12
+#define ARMV6_PMCR_EVT_COUNT1_MASK     (0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT)
+
+#define ARMV6_PMCR_OVERFLOWED_MASK \
+       (ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \
+        ARMV6_PMCR_CCOUNT_OVERFLOW)
+
+static inline int
+armv6_pmcr_has_overflowed(unsigned long pmcr)
+{
+       return pmcr & ARMV6_PMCR_OVERFLOWED_MASK;
+}
+
+static inline int
+armv6_pmcr_counter_has_overflowed(unsigned long pmcr,
+                                 enum armv6_counters counter)
+{
+       int ret = 0;
+
+       if (ARMV6_CYCLE_COUNTER == counter)
+               ret = pmcr & ARMV6_PMCR_CCOUNT_OVERFLOW;
+       else if (ARMV6_COUNTER0 == counter)
+               ret = pmcr & ARMV6_PMCR_COUNT0_OVERFLOW;
+       else if (ARMV6_COUNTER1 == counter)
+               ret = pmcr & ARMV6_PMCR_COUNT1_OVERFLOW;
+       else
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+
+       return ret;
+}
+
+static inline u32
+armv6pmu_read_counter(int counter)
+{
+       unsigned long value = 0;
+
+       if (ARMV6_CYCLE_COUNTER == counter)
+               asm volatile("mrc   p15, 0, %0, c15, c12, 1" : "=r"(value));
+       else if (ARMV6_COUNTER0 == counter)
+               asm volatile("mrc   p15, 0, %0, c15, c12, 2" : "=r"(value));
+       else if (ARMV6_COUNTER1 == counter)
+               asm volatile("mrc   p15, 0, %0, c15, c12, 3" : "=r"(value));
+       else
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+
+       return value;
+}
+
+static inline void
+armv6pmu_write_counter(int counter,
+                      u32 value)
+{
+       if (ARMV6_CYCLE_COUNTER == counter)
+               asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value));
+       else if (ARMV6_COUNTER0 == counter)
+               asm volatile("mcr   p15, 0, %0, c15, c12, 2" : : "r"(value));
+       else if (ARMV6_COUNTER1 == counter)
+               asm volatile("mcr   p15, 0, %0, c15, c12, 3" : : "r"(value));
+       else
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+}
+
+static void
+armv6pmu_enable_event(struct hw_perf_event *hwc,
+                     int idx)
+{
+       unsigned long val, mask, evt, flags;
+
+       if (ARMV6_CYCLE_COUNTER == idx) {
+               mask    = 0;
+               evt     = ARMV6_PMCR_CCOUNT_IEN;
+       } else if (ARMV6_COUNTER0 == idx) {
+               mask    = ARMV6_PMCR_EVT_COUNT0_MASK;
+               evt     = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) |
+                         ARMV6_PMCR_COUNT0_IEN;
+       } else if (ARMV6_COUNTER1 == idx) {
+               mask    = ARMV6_PMCR_EVT_COUNT1_MASK;
+               evt     = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) |
+                         ARMV6_PMCR_COUNT1_IEN;
+       } else {
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       /*
+        * Mask out the current event and set the counter to count the event
+        * that we're interested in.
+        */
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~mask;
+       val |= evt;
+       armv6_pmcr_write(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static irqreturn_t
+armv6pmu_handle_irq(int irq_num,
+                   void *dev)
+{
+       unsigned long pmcr = armv6_pmcr_read();
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct pt_regs *regs;
+       int idx;
+
+       if (!armv6_pmcr_has_overflowed(pmcr))
+               return IRQ_NONE;
+
+       regs = get_irq_regs();
+
+       /*
+        * The interrupts are cleared by writing the overflow flags back to
+        * the control register. All of the other bits don't have any effect
+        * if they are rewritten, so write the whole value back.
+        */
+       armv6_pmcr_write(pmcr);
+
+       perf_sample_data_init(&data, 0);
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+               struct perf_event *event = cpuc->events[idx];
+               struct hw_perf_event *hwc;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               /*
+                * We have a single interrupt for all counters. Check that
+                * each counter has overflowed before we process it.
+                */
+               if (!armv6_pmcr_counter_has_overflowed(pmcr, idx))
+                       continue;
+
+               hwc = &event->hw;
+               armpmu_event_update(event, hwc, idx);
+               data.period = event->hw.last_period;
+               if (!armpmu_event_set_period(event, hwc, idx))
+                       continue;
+
+               if (perf_event_overflow(event, 0, &data, regs))
+                       armpmu->disable(hwc, idx);
+       }
+
+       /*
+        * Handle the pending perf events.
+        *
+        * Note: this call *must* be run with interrupts disabled. For
+        * platforms that can have the PMU interrupts raised as an NMI, this
+        * will not work.
+        */
+       irq_work_run();
+
+       return IRQ_HANDLED;
+}
+
+static void
+armv6pmu_start(void)
+{
+       unsigned long flags, val;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val |= ARMV6_PMCR_ENABLE;
+       armv6_pmcr_write(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+armv6pmu_stop(void)
+{
+       unsigned long flags, val;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~ARMV6_PMCR_ENABLE;
+       armv6_pmcr_write(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int
+armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
+                      struct hw_perf_event *event)
+{
+       /* Always place a cycle counter into the cycle counter. */
+       if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) {
+               if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask))
+                       return -EAGAIN;
+
+               return ARMV6_CYCLE_COUNTER;
+       } else {
+               /*
+                * For anything other than a cycle counter, try and use
+                * counter0 and counter1.
+                */
+               if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask))
+                       return ARMV6_COUNTER1;
+
+               if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask))
+                       return ARMV6_COUNTER0;
+
+               /* The counters are all in use. */
+               return -EAGAIN;
+       }
+}
+
+static void
+armv6pmu_disable_event(struct hw_perf_event *hwc,
+                      int idx)
+{
+       unsigned long val, mask, evt, flags;
+
+       if (ARMV6_CYCLE_COUNTER == idx) {
+               mask    = ARMV6_PMCR_CCOUNT_IEN;
+               evt     = 0;
+       } else if (ARMV6_COUNTER0 == idx) {
+               mask    = ARMV6_PMCR_COUNT0_IEN | ARMV6_PMCR_EVT_COUNT0_MASK;
+               evt     = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT0_SHIFT;
+       } else if (ARMV6_COUNTER1 == idx) {
+               mask    = ARMV6_PMCR_COUNT1_IEN | ARMV6_PMCR_EVT_COUNT1_MASK;
+               evt     = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT1_SHIFT;
+       } else {
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       /*
+        * Mask out the current event and set the counter to count the number
+        * of ETM bus signal assertion cycles. The external reporting should
+        * be disabled and so this should never increment.
+        */
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~mask;
+       val |= evt;
+       armv6_pmcr_write(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
+                             int idx)
+{
+       unsigned long val, mask, flags, evt = 0;
+
+       if (ARMV6_CYCLE_COUNTER == idx) {
+               mask    = ARMV6_PMCR_CCOUNT_IEN;
+       } else if (ARMV6_COUNTER0 == idx) {
+               mask    = ARMV6_PMCR_COUNT0_IEN;
+       } else if (ARMV6_COUNTER1 == idx) {
+               mask    = ARMV6_PMCR_COUNT1_IEN;
+       } else {
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       /*
+        * Unlike UP ARMv6, we don't have a way of stopping the counters. We
+        * simply disable the interrupt reporting.
+        */
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = armv6_pmcr_read();
+       val &= ~mask;
+       val |= evt;
+       armv6_pmcr_write(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static const struct arm_pmu armv6pmu = {
+       .id                     = ARM_PERF_PMU_ID_V6,
+       .name                   = "v6",
+       .handle_irq             = armv6pmu_handle_irq,
+       .enable                 = armv6pmu_enable_event,
+       .disable                = armv6pmu_disable_event,
+       .read_counter           = armv6pmu_read_counter,
+       .write_counter          = armv6pmu_write_counter,
+       .get_event_idx          = armv6pmu_get_event_idx,
+       .start                  = armv6pmu_start,
+       .stop                   = armv6pmu_stop,
+       .cache_map              = &armv6_perf_cache_map,
+       .event_map              = &armv6_perf_map,
+       .raw_event_mask         = 0xFF,
+       .num_events             = 3,
+       .max_period             = (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init armv6pmu_init(void)
+{
+       return &armv6pmu;
+}
+
+/*
+ * ARMv6mpcore is almost identical to single core ARMv6 with the exception
+ * that some of the events have different enumerations and that there is no
+ * *hack* to stop the programmable counters. To stop the counters we simply
+ * disable the interrupt reporting and update the event. When unthrottling we
+ * reset the period and enable the interrupt reporting.
+ */
+static const struct arm_pmu armv6mpcore_pmu = {
+       .id                     = ARM_PERF_PMU_ID_V6MP,
+       .name                   = "v6mpcore",
+       .handle_irq             = armv6pmu_handle_irq,
+       .enable                 = armv6pmu_enable_event,
+       .disable                = armv6mpcore_pmu_disable_event,
+       .read_counter           = armv6pmu_read_counter,
+       .write_counter          = armv6pmu_write_counter,
+       .get_event_idx          = armv6pmu_get_event_idx,
+       .start                  = armv6pmu_start,
+       .stop                   = armv6pmu_stop,
+       .cache_map              = &armv6mpcore_perf_cache_map,
+       .event_map              = &armv6mpcore_perf_map,
+       .raw_event_mask         = 0xFF,
+       .num_events             = 3,
+       .max_period             = (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+{
+       return &armv6mpcore_pmu;
+}
+#else
+static const struct arm_pmu *__init armv6pmu_init(void)
+{
+       return NULL;
+}
+
+static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
+{
+       return NULL;
+}
+#endif /* CONFIG_CPU_V6 */
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
new file mode 100644 (file)
index 0000000..2e14025
--- /dev/null
@@ -0,0 +1,906 @@
+/*
+ * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code.
+ *
+ * ARMv7 support: Jean Pihet <jpihet@mvista.com>
+ * 2010 (c) MontaVista Software, LLC.
+ *
+ * Copied from ARMv6 code, with the low level code inspired
+ *  by the ARMv7 Oprofile code.
+ *
+ * Cortex-A8 has up to 4 configurable performance counters and
+ *  a single cycle counter.
+ * Cortex-A9 has up to 31 configurable performance counters and
+ *  a single cycle counter.
+ *
+ * All counters can be enabled/disabled and IRQ masked separately. The cycle
+ *  counter and all 4 performance counters together can be reset separately.
+ */
+
+#ifdef CONFIG_CPU_V7
+/* Common ARMv7 event types */
+enum armv7_perf_types {
+       ARMV7_PERFCTR_PMNC_SW_INCR              = 0x00,
+       ARMV7_PERFCTR_IFETCH_MISS               = 0x01,
+       ARMV7_PERFCTR_ITLB_MISS                 = 0x02,
+       ARMV7_PERFCTR_DCACHE_REFILL             = 0x03,
+       ARMV7_PERFCTR_DCACHE_ACCESS             = 0x04,
+       ARMV7_PERFCTR_DTLB_REFILL               = 0x05,
+       ARMV7_PERFCTR_DREAD                     = 0x06,
+       ARMV7_PERFCTR_DWRITE                    = 0x07,
+
+       ARMV7_PERFCTR_EXC_TAKEN                 = 0x09,
+       ARMV7_PERFCTR_EXC_EXECUTED              = 0x0A,
+       ARMV7_PERFCTR_CID_WRITE                 = 0x0B,
+       /* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS.
+        * It counts:
+        *  - all branch instructions,
+        *  - instructions that explicitly write the PC,
+        *  - exception generating instructions.
+        */
+       ARMV7_PERFCTR_PC_WRITE                  = 0x0C,
+       ARMV7_PERFCTR_PC_IMM_BRANCH             = 0x0D,
+       ARMV7_PERFCTR_UNALIGNED_ACCESS          = 0x0F,
+       ARMV7_PERFCTR_PC_BRANCH_MIS_PRED        = 0x10,
+       ARMV7_PERFCTR_CLOCK_CYCLES              = 0x11,
+
+       ARMV7_PERFCTR_PC_BRANCH_MIS_USED        = 0x12,
+
+       ARMV7_PERFCTR_CPU_CYCLES                = 0xFF
+};
+
+/* ARMv7 Cortex-A8 specific event types */
+enum armv7_a8_perf_types {
+       ARMV7_PERFCTR_INSTR_EXECUTED            = 0x08,
+
+       ARMV7_PERFCTR_PC_PROC_RETURN            = 0x0E,
+
+       ARMV7_PERFCTR_WRITE_BUFFER_FULL         = 0x40,
+       ARMV7_PERFCTR_L2_STORE_MERGED           = 0x41,
+       ARMV7_PERFCTR_L2_STORE_BUFF             = 0x42,
+       ARMV7_PERFCTR_L2_ACCESS                 = 0x43,
+       ARMV7_PERFCTR_L2_CACH_MISS              = 0x44,
+       ARMV7_PERFCTR_AXI_READ_CYCLES           = 0x45,
+       ARMV7_PERFCTR_AXI_WRITE_CYCLES          = 0x46,
+       ARMV7_PERFCTR_MEMORY_REPLAY             = 0x47,
+       ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY   = 0x48,
+       ARMV7_PERFCTR_L1_DATA_MISS              = 0x49,
+       ARMV7_PERFCTR_L1_INST_MISS              = 0x4A,
+       ARMV7_PERFCTR_L1_DATA_COLORING          = 0x4B,
+       ARMV7_PERFCTR_L1_NEON_DATA              = 0x4C,
+       ARMV7_PERFCTR_L1_NEON_CACH_DATA         = 0x4D,
+       ARMV7_PERFCTR_L2_NEON                   = 0x4E,
+       ARMV7_PERFCTR_L2_NEON_HIT               = 0x4F,
+       ARMV7_PERFCTR_L1_INST                   = 0x50,
+       ARMV7_PERFCTR_PC_RETURN_MIS_PRED        = 0x51,
+       ARMV7_PERFCTR_PC_BRANCH_FAILED          = 0x52,
+       ARMV7_PERFCTR_PC_BRANCH_TAKEN           = 0x53,
+       ARMV7_PERFCTR_PC_BRANCH_EXECUTED        = 0x54,
+       ARMV7_PERFCTR_OP_EXECUTED               = 0x55,
+       ARMV7_PERFCTR_CYCLES_INST_STALL         = 0x56,
+       ARMV7_PERFCTR_CYCLES_INST               = 0x57,
+       ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL    = 0x58,
+       ARMV7_PERFCTR_CYCLES_NEON_INST_STALL    = 0x59,
+       ARMV7_PERFCTR_NEON_CYCLES               = 0x5A,
+
+       ARMV7_PERFCTR_PMU0_EVENTS               = 0x70,
+       ARMV7_PERFCTR_PMU1_EVENTS               = 0x71,
+       ARMV7_PERFCTR_PMU_EVENTS                = 0x72,
+};
+
+/* ARMv7 Cortex-A9 specific event types */
+enum armv7_a9_perf_types {
+       ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC     = 0x40,
+       ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC     = 0x41,
+       ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC       = 0x42,
+
+       ARMV7_PERFCTR_COHERENT_LINE_MISS        = 0x50,
+       ARMV7_PERFCTR_COHERENT_LINE_HIT         = 0x51,
+
+       ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES   = 0x60,
+       ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES   = 0x61,
+       ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES = 0x62,
+       ARMV7_PERFCTR_STREX_EXECUTED_PASSED     = 0x63,
+       ARMV7_PERFCTR_STREX_EXECUTED_FAILED     = 0x64,
+       ARMV7_PERFCTR_DATA_EVICTION             = 0x65,
+       ARMV7_PERFCTR_ISSUE_STAGE_NO_INST       = 0x66,
+       ARMV7_PERFCTR_ISSUE_STAGE_EMPTY         = 0x67,
+       ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE  = 0x68,
+
+       ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS = 0x6E,
+
+       ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST   = 0x70,
+       ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST = 0x71,
+       ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST  = 0x72,
+       ARMV7_PERFCTR_FP_EXECUTED_INST          = 0x73,
+       ARMV7_PERFCTR_NEON_EXECUTED_INST        = 0x74,
+
+       ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES = 0x80,
+       ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES  = 0x81,
+       ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES        = 0x82,
+       ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES        = 0x83,
+       ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES  = 0x84,
+       ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES  = 0x85,
+       ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES      = 0x86,
+
+       ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES  = 0x8A,
+       ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES = 0x8B,
+
+       ARMV7_PERFCTR_ISB_INST                  = 0x90,
+       ARMV7_PERFCTR_DSB_INST                  = 0x91,
+       ARMV7_PERFCTR_DMB_INST                  = 0x92,
+       ARMV7_PERFCTR_EXT_INTERRUPTS            = 0x93,
+
+       ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED     = 0xA0,
+       ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED       = 0xA1,
+       ARMV7_PERFCTR_PLE_FIFO_FLUSH            = 0xA2,
+       ARMV7_PERFCTR_PLE_RQST_COMPLETED        = 0xA3,
+       ARMV7_PERFCTR_PLE_FIFO_OVERFLOW         = 0xA4,
+       ARMV7_PERFCTR_PLE_RQST_PROG             = 0xA5
+};
+
+/*
+ * Cortex-A8 HW events mapping
+ *
+ * The hardware events that we support. We do support cache operations but
+ * we have harvard caches and no way to combine instruction and data
+ * accesses/misses in hardware.
+ */
+static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV7_PERFCTR_INSTR_EXECUTED,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+       [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                         [PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * Only ITLB misses and DTLB refills are supported.
+                * If users want the DTLB refills misses a raw counter
+                * must be used.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+/*
+ * Cortex-A9 HW events mapping
+ */
+static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]        =
+                                       ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT,
+       [PERF_COUNT_HW_CACHE_MISSES]        = ARMV7_PERFCTR_COHERENT_LINE_MISS,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+       [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                         [PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               /*
+                * Only ITLB misses and DTLB refills are supported.
+                * If users want the DTLB refills misses a raw counter
+                * must be used.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
+                       [C(RESULT_MISS)]
+                                       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+/*
+ * Perf Events counters
+ */
+enum armv7_counters {
+       ARMV7_CYCLE_COUNTER             = 1,    /* Cycle counter */
+       ARMV7_COUNTER0                  = 2,    /* First event counter */
+};
+
+/*
+ * The cycle counter is ARMV7_CYCLE_COUNTER.
+ * The first event counter is ARMV7_COUNTER0.
+ * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
+ */
+#define        ARMV7_COUNTER_LAST      (ARMV7_COUNTER0 + armpmu->num_events - 1)
+
+/*
+ * ARMv7 low level PMNC access
+ */
+
+/*
+ * Per-CPU PMNC: config reg
+ */
+#define ARMV7_PMNC_E           (1 << 0) /* Enable all counters */
+#define ARMV7_PMNC_P           (1 << 1) /* Reset all counters */
+#define ARMV7_PMNC_C           (1 << 2) /* Cycle counter reset */
+#define ARMV7_PMNC_D           (1 << 3) /* CCNT counts every 64th cpu cycle */
+#define ARMV7_PMNC_X           (1 << 4) /* Export to ETM */
+#define ARMV7_PMNC_DP          (1 << 5) /* Disable CCNT if non-invasive debug*/
+#define        ARMV7_PMNC_N_SHIFT      11       /* Number of counters supported */
+#define        ARMV7_PMNC_N_MASK       0x1f
+#define        ARMV7_PMNC_MASK         0x3f     /* Mask for writable bits */
+
+/*
+ * Available counters
+ */
+#define ARMV7_CNT0             0       /* First event counter */
+#define ARMV7_CCNT             31      /* Cycle counter */
+
+/* Perf Event to low level counters mapping */
+#define ARMV7_EVENT_CNT_TO_CNTx        (ARMV7_COUNTER0 - ARMV7_CNT0)
+
+/*
+ * CNTENS: counters enable reg
+ */
+#define ARMV7_CNTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_CNTENS_C         (1 << ARMV7_CCNT)
+
+/*
+ * CNTENC: counters disable reg
+ */
+#define ARMV7_CNTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_CNTENC_C         (1 << ARMV7_CCNT)
+
+/*
+ * INTENS: counters overflow interrupt enable reg
+ */
+#define ARMV7_INTENS_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_INTENS_C         (1 << ARMV7_CCNT)
+
+/*
+ * INTENC: counters overflow interrupt disable reg
+ */
+#define ARMV7_INTENC_P(idx)    (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_INTENC_C         (1 << ARMV7_CCNT)
+
+/*
+ * EVTSEL: Event selection reg
+ */
+#define        ARMV7_EVTSEL_MASK       0xff            /* Mask for writable bits */
+
+/*
+ * SELECT: Counter selection reg
+ */
+#define        ARMV7_SELECT_MASK       0x1f            /* Mask for writable bits */
+
+/*
+ * FLAG: counters overflow flag status reg
+ */
+#define ARMV7_FLAG_P(idx)      (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
+#define ARMV7_FLAG_C           (1 << ARMV7_CCNT)
+#define        ARMV7_FLAG_MASK         0xffffffff      /* Mask for writable bits */
+#define        ARMV7_OVERFLOWED_MASK   ARMV7_FLAG_MASK
+
+static inline unsigned long armv7_pmnc_read(void)
+{
+       u32 val;
+       asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
+       return val;
+}
+
+static inline void armv7_pmnc_write(unsigned long val)
+{
+       val &= ARMV7_PMNC_MASK;
+       asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
+}
+
+static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
+{
+       return pmnc & ARMV7_OVERFLOWED_MASK;
+}
+
+static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
+                                       enum armv7_counters counter)
+{
+       int ret = 0;
+
+       if (counter == ARMV7_CYCLE_COUNTER)
+               ret = pmnc & ARMV7_FLAG_C;
+       else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
+               ret = pmnc & ARMV7_FLAG_P(counter);
+       else
+               pr_err("CPU%u checking wrong counter %d overflow status\n",
+                       smp_processor_id(), counter);
+
+       return ret;
+}
+
+static inline int armv7_pmnc_select_counter(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
+               pr_err("CPU%u selecting wrong PMNC counter"
+                       " %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
+       asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7pmu_read_counter(int idx)
+{
+       unsigned long value = 0;
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
+       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
+               if (armv7_pmnc_select_counter(idx) == idx)
+                       asm volatile("mrc p15, 0, %0, c9, c13, 2"
+                                    : "=r" (value));
+       } else
+               pr_err("CPU%u reading wrong counter %d\n",
+                       smp_processor_id(), idx);
+
+       return value;
+}
+
+static inline void armv7pmu_write_counter(int idx, u32 value)
+{
+       if (idx == ARMV7_CYCLE_COUNTER)
+               asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
+       else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
+               if (armv7_pmnc_select_counter(idx) == idx)
+                       asm volatile("mcr p15, 0, %0, c9, c13, 2"
+                                    : : "r" (value));
+       } else
+               pr_err("CPU%u writing wrong counter %d\n",
+                       smp_processor_id(), idx);
+}
+
+static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
+{
+       if (armv7_pmnc_select_counter(idx) == idx) {
+               val &= ARMV7_EVTSEL_MASK;
+               asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
+       }
+}
+
+static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u enabling wrong PMNC counter"
+                       " %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_CNTENS_C;
+       else
+               val = ARMV7_CNTENS_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
+{
+       u32 val;
+
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u disabling wrong PMNC counter"
+                       " %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_CNTENC_C;
+       else
+               val = ARMV7_CNTENC_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u enabling wrong PMNC counter"
+                       " interrupt enable %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_INTENS_C;
+       else
+               val = ARMV7_INTENS_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
+{
+       u32 val;
+
+       if ((idx != ARMV7_CYCLE_COUNTER) &&
+           ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
+               pr_err("CPU%u disabling wrong PMNC counter"
+                       " interrupt enable %d\n", smp_processor_id(), idx);
+               return -1;
+       }
+
+       if (idx == ARMV7_CYCLE_COUNTER)
+               val = ARMV7_INTENC_C;
+       else
+               val = ARMV7_INTENC_P(idx);
+
+       asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
+
+       return idx;
+}
+
+static inline u32 armv7_pmnc_getreset_flags(void)
+{
+       u32 val;
+
+       /* Read */
+       asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
+
+       /* Write to clear flags */
+       val &= ARMV7_FLAG_MASK;
+       asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
+
+       return val;
+}
+
+#ifdef DEBUG
+static void armv7_pmnc_dump_regs(void)
+{
+       u32 val;
+       unsigned int cnt;
+
+       printk(KERN_INFO "PMNC registers dump:\n");
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
+       printk(KERN_INFO "PMNC  =0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
+       printk(KERN_INFO "CNTENS=0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
+       printk(KERN_INFO "INTENS=0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
+       printk(KERN_INFO "FLAGS =0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
+       printk(KERN_INFO "SELECT=0x%08x\n", val);
+
+       asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
+       printk(KERN_INFO "CCNT  =0x%08x\n", val);
+
+       for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
+               armv7_pmnc_select_counter(cnt);
+               asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
+               printk(KERN_INFO "CNT[%d] count =0x%08x\n",
+                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+               asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
+               printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
+                       cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
+       }
+}
+#endif
+
+static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long flags;
+
+       /*
+        * Enable counter and interrupt, and set the counter to count
+        * the event that we're interested in.
+        */
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+
+       /*
+        * Disable counter
+        */
+       armv7_pmnc_disable_counter(idx);
+
+       /*
+        * Set event (if destined for PMNx counters)
+        * We don't need to set the event if it's a cycle count
+        */
+       if (idx != ARMV7_CYCLE_COUNTER)
+               armv7_pmnc_write_evtsel(idx, hwc->config_base);
+
+       /*
+        * Enable interrupt for this counter
+        */
+       armv7_pmnc_enable_intens(idx);
+
+       /*
+        * Enable counter
+        */
+       armv7_pmnc_enable_counter(idx);
+
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long flags;
+
+       /*
+        * Disable counter and interrupt
+        */
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+
+       /*
+        * Disable counter
+        */
+       armv7_pmnc_disable_counter(idx);
+
+       /*
+        * Disable interrupt for this counter
+        */
+       armv7_pmnc_disable_intens(idx);
+
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
+{
+       unsigned long pmnc;
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct pt_regs *regs;
+       int idx;
+
+       /*
+        * Get and reset the IRQ flags
+        */
+       pmnc = armv7_pmnc_getreset_flags();
+
+       /*
+        * Did an overflow occur?
+        */
+       if (!armv7_pmnc_has_overflowed(pmnc))
+               return IRQ_NONE;
+
+       /*
+        * Handle the counter(s) overflow(s)
+        */
+       regs = get_irq_regs();
+
+       perf_sample_data_init(&data, 0);
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+               struct perf_event *event = cpuc->events[idx];
+               struct hw_perf_event *hwc;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               /*
+                * We have a single interrupt for all counters. Check that
+                * each counter has overflowed before we process it.
+                */
+               if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
+                       continue;
+
+               hwc = &event->hw;
+               armpmu_event_update(event, hwc, idx);
+               data.period = event->hw.last_period;
+               if (!armpmu_event_set_period(event, hwc, idx))
+                       continue;
+
+               if (perf_event_overflow(event, 0, &data, regs))
+                       armpmu->disable(hwc, idx);
+       }
+
+       /*
+        * Handle the pending perf events.
+        *
+        * Note: this call *must* be run with interrupts disabled. For
+        * platforms that can have the PMU interrupts raised as an NMI, this
+        * will not work.
+        */
+       irq_work_run();
+
+       return IRQ_HANDLED;
+}
+
+static void armv7pmu_start(void)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       /* Enable all counters */
+       armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void armv7pmu_stop(void)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       /* Disable all counters */
+       armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
+                                 struct hw_perf_event *event)
+{
+       int idx;
+
+       /* Always place a cycle counter into the cycle counter. */
+       if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
+               if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
+                       return -EAGAIN;
+
+               return ARMV7_CYCLE_COUNTER;
+       } else {
+               /*
+                * For anything other than a cycle counter, try and use
+                * the events counters
+                */
+               for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
+                       if (!test_and_set_bit(idx, cpuc->used_mask))
+                               return idx;
+               }
+
+               /* The counters are all in use. */
+               return -EAGAIN;
+       }
+}
+
+static struct arm_pmu armv7pmu = {
+       .handle_irq             = armv7pmu_handle_irq,
+       .enable                 = armv7pmu_enable_event,
+       .disable                = armv7pmu_disable_event,
+       .read_counter           = armv7pmu_read_counter,
+       .write_counter          = armv7pmu_write_counter,
+       .get_event_idx          = armv7pmu_get_event_idx,
+       .start                  = armv7pmu_start,
+       .stop                   = armv7pmu_stop,
+       .raw_event_mask         = 0xFF,
+       .max_period             = (1LLU << 32) - 1,
+};
+
+static u32 __init armv7_reset_read_pmnc(void)
+{
+       u32 nb_cnt;
+
+       /* Initialize & Reset PMNC: C and P bits */
+       armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
+
+       /* Read the nb of CNTx counters supported from PMNC */
+       nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
+
+       /* Add the CPU cycles counter and return */
+       return nb_cnt + 1;
+}
+
+static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+{
+       armv7pmu.id             = ARM_PERF_PMU_ID_CA8;
+       armv7pmu.name           = "ARMv7 Cortex-A8";
+       armv7pmu.cache_map      = &armv7_a8_perf_cache_map;
+       armv7pmu.event_map      = &armv7_a8_perf_map;
+       armv7pmu.num_events     = armv7_reset_read_pmnc();
+       return &armv7pmu;
+}
+
+static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+{
+       armv7pmu.id             = ARM_PERF_PMU_ID_CA9;
+       armv7pmu.name           = "ARMv7 Cortex-A9";
+       armv7pmu.cache_map      = &armv7_a9_perf_cache_map;
+       armv7pmu.event_map      = &armv7_a9_perf_map;
+       armv7pmu.num_events     = armv7_reset_read_pmnc();
+       return &armv7pmu;
+}
+#else
+static const struct arm_pmu *__init armv7_a8_pmu_init(void)
+{
+       return NULL;
+}
+
+static const struct arm_pmu *__init armv7_a9_pmu_init(void)
+{
+       return NULL;
+}
+#endif /* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
new file mode 100644 (file)
index 0000000..28cd3b0
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * ARMv5 [xscale] Performance counter handling code.
+ *
+ * Copyright (C) 2010, ARM Ltd., Will Deacon <will.deacon@arm.com>
+ *
+ * Based on the previous xscale OProfile code.
+ *
+ * There are two variants of the xscale PMU that we support:
+ *     - xscale1pmu: 2 event counters and a cycle counter
+ *     - xscale2pmu: 4 event counters and a cycle counter
+ * The two variants share event definitions, but have different
+ * PMU structures.
+ */
+
+#ifdef CONFIG_CPU_XSCALE
+enum xscale_perf_types {
+       XSCALE_PERFCTR_ICACHE_MISS              = 0x00,
+       XSCALE_PERFCTR_ICACHE_NO_DELIVER        = 0x01,
+       XSCALE_PERFCTR_DATA_STALL               = 0x02,
+       XSCALE_PERFCTR_ITLB_MISS                = 0x03,
+       XSCALE_PERFCTR_DTLB_MISS                = 0x04,
+       XSCALE_PERFCTR_BRANCH                   = 0x05,
+       XSCALE_PERFCTR_BRANCH_MISS              = 0x06,
+       XSCALE_PERFCTR_INSTRUCTION              = 0x07,
+       XSCALE_PERFCTR_DCACHE_FULL_STALL        = 0x08,
+       XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG = 0x09,
+       XSCALE_PERFCTR_DCACHE_ACCESS            = 0x0A,
+       XSCALE_PERFCTR_DCACHE_MISS              = 0x0B,
+       XSCALE_PERFCTR_DCACHE_WRITE_BACK        = 0x0C,
+       XSCALE_PERFCTR_PC_CHANGED               = 0x0D,
+       XSCALE_PERFCTR_BCU_REQUEST              = 0x10,
+       XSCALE_PERFCTR_BCU_FULL                 = 0x11,
+       XSCALE_PERFCTR_BCU_DRAIN                = 0x12,
+       XSCALE_PERFCTR_BCU_ECC_NO_ELOG          = 0x14,
+       XSCALE_PERFCTR_BCU_1_BIT_ERR            = 0x15,
+       XSCALE_PERFCTR_RMW                      = 0x16,
+       /* XSCALE_PERFCTR_CCNT is not hardware defined */
+       XSCALE_PERFCTR_CCNT                     = 0xFE,
+       XSCALE_PERFCTR_UNUSED                   = 0xFF,
+};
+
+enum xscale_counters {
+       XSCALE_CYCLE_COUNTER    = 1,
+       XSCALE_COUNTER0,
+       XSCALE_COUNTER1,
+       XSCALE_COUNTER2,
+       XSCALE_COUNTER3,
+};
+
+static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = XSCALE_PERFCTR_CCNT,
+       [PERF_COUNT_HW_INSTRUCTIONS]        = XSCALE_PERFCTR_INSTRUCTION,
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
+       [PERF_COUNT_HW_BRANCH_MISSES]       = XSCALE_PERFCTR_BRANCH_MISS,
+       [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                          [PERF_COUNT_HW_CACHE_OP_MAX]
+                                          [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = XSCALE_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DCACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = XSCALE_PERFCTR_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DCACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ICACHE_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_DTLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ITLB_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
+#define        XSCALE_PMU_ENABLE       0x001
+#define XSCALE_PMN_RESET       0x002
+#define        XSCALE_CCNT_RESET       0x004
+#define        XSCALE_PMU_RESET        (CCNT_RESET | PMN_RESET)
+#define XSCALE_PMU_CNT64       0x008
+
+#define XSCALE1_OVERFLOWED_MASK        0x700
+#define XSCALE1_CCOUNT_OVERFLOW        0x400
+#define XSCALE1_COUNT0_OVERFLOW        0x100
+#define XSCALE1_COUNT1_OVERFLOW        0x200
+#define XSCALE1_CCOUNT_INT_EN  0x040
+#define XSCALE1_COUNT0_INT_EN  0x010
+#define XSCALE1_COUNT1_INT_EN  0x020
+#define XSCALE1_COUNT0_EVT_SHFT        12
+#define XSCALE1_COUNT0_EVT_MASK        (0xff << XSCALE1_COUNT0_EVT_SHFT)
+#define XSCALE1_COUNT1_EVT_SHFT        20
+#define XSCALE1_COUNT1_EVT_MASK        (0xff << XSCALE1_COUNT1_EVT_SHFT)
+
+static inline u32
+xscale1pmu_read_pmnc(void)
+{
+       u32 val;
+       asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
+       return val;
+}
+
+static inline void
+xscale1pmu_write_pmnc(u32 val)
+{
+       /* upper 4bits and 7, 11 are write-as-0 */
+       val &= 0xffff77f;
+       asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
+}
+
+static inline int
+xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
+                                       enum xscale_counters counter)
+{
+       int ret = 0;
+
+       switch (counter) {
+       case XSCALE_CYCLE_COUNTER:
+               ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
+               break;
+       case XSCALE_COUNTER0:
+               ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
+               break;
+       case XSCALE_COUNTER1:
+               ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
+               break;
+       default:
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+       }
+
+       return ret;
+}
+
+static irqreturn_t
+xscale1pmu_handle_irq(int irq_num, void *dev)
+{
+       unsigned long pmnc;
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct pt_regs *regs;
+       int idx;
+
+       /*
+        * NOTE: there's an A stepping erratum that states if an overflow
+        *       bit already exists and another occurs, the previous
+        *       Overflow bit gets cleared. There's no workaround.
+        *       Fixed in B stepping or later.
+        */
+       pmnc = xscale1pmu_read_pmnc();
+
+       /*
+        * Write the value back to clear the overflow flags. Overflow
+        * flags remain in pmnc for use below. We also disable the PMU
+        * while we process the interrupt.
+        */
+       xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
+
+       if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
+               return IRQ_NONE;
+
+       regs = get_irq_regs();
+
+       perf_sample_data_init(&data, 0);
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+               struct perf_event *event = cpuc->events[idx];
+               struct hw_perf_event *hwc;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
+                       continue;
+
+               hwc = &event->hw;
+               armpmu_event_update(event, hwc, idx);
+               data.period = event->hw.last_period;
+               if (!armpmu_event_set_period(event, hwc, idx))
+                       continue;
+
+               if (perf_event_overflow(event, 0, &data, regs))
+                       armpmu->disable(hwc, idx);
+       }
+
+       irq_work_run();
+
+       /*
+        * Re-enable the PMU.
+        */
+       pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
+       xscale1pmu_write_pmnc(pmnc);
+
+       return IRQ_HANDLED;
+}
+
+static void
+xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long val, mask, evt, flags;
+
+       switch (idx) {
+       case XSCALE_CYCLE_COUNTER:
+               mask = 0;
+               evt = XSCALE1_CCOUNT_INT_EN;
+               break;
+       case XSCALE_COUNTER0:
+               mask = XSCALE1_COUNT0_EVT_MASK;
+               evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
+                       XSCALE1_COUNT0_INT_EN;
+               break;
+       case XSCALE_COUNTER1:
+               mask = XSCALE1_COUNT1_EVT_MASK;
+               evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
+                       XSCALE1_COUNT1_INT_EN;
+               break;
+       default:
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = xscale1pmu_read_pmnc();
+       val &= ~mask;
+       val |= evt;
+       xscale1pmu_write_pmnc(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long val, mask, evt, flags;
+
+       switch (idx) {
+       case XSCALE_CYCLE_COUNTER:
+               mask = XSCALE1_CCOUNT_INT_EN;
+               evt = 0;
+               break;
+       case XSCALE_COUNTER0:
+               mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
+               evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
+               break;
+       case XSCALE_COUNTER1:
+               mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
+               evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
+               break;
+       default:
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = xscale1pmu_read_pmnc();
+       val &= ~mask;
+       val |= evt;
+       xscale1pmu_write_pmnc(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int
+xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
+                       struct hw_perf_event *event)
+{
+       if (XSCALE_PERFCTR_CCNT == event->config_base) {
+               if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
+                       return -EAGAIN;
+
+               return XSCALE_CYCLE_COUNTER;
+       } else {
+               if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask))
+                       return XSCALE_COUNTER1;
+
+               if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask))
+                       return XSCALE_COUNTER0;
+
+               return -EAGAIN;
+       }
+}
+
+static void
+xscale1pmu_start(void)
+{
+       unsigned long flags, val;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = xscale1pmu_read_pmnc();
+       val |= XSCALE_PMU_ENABLE;
+       xscale1pmu_write_pmnc(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+xscale1pmu_stop(void)
+{
+       unsigned long flags, val;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = xscale1pmu_read_pmnc();
+       val &= ~XSCALE_PMU_ENABLE;
+       xscale1pmu_write_pmnc(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static inline u32
+xscale1pmu_read_counter(int counter)
+{
+       u32 val = 0;
+
+       switch (counter) {
+       case XSCALE_CYCLE_COUNTER:
+               asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
+               break;
+       case XSCALE_COUNTER0:
+               asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
+               break;
+       case XSCALE_COUNTER1:
+               asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
+               break;
+       }
+
+       return val;
+}
+
+static inline void
+xscale1pmu_write_counter(int counter, u32 val)
+{
+       switch (counter) {
+       case XSCALE_CYCLE_COUNTER:
+               asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
+               break;
+       case XSCALE_COUNTER0:
+               asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
+               break;
+       case XSCALE_COUNTER1:
+               asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
+               break;
+       }
+}
+
+static const struct arm_pmu xscale1pmu = {
+       .id             = ARM_PERF_PMU_ID_XSCALE1,
+       .name           = "xscale1",
+       .handle_irq     = xscale1pmu_handle_irq,
+       .enable         = xscale1pmu_enable_event,
+       .disable        = xscale1pmu_disable_event,
+       .read_counter   = xscale1pmu_read_counter,
+       .write_counter  = xscale1pmu_write_counter,
+       .get_event_idx  = xscale1pmu_get_event_idx,
+       .start          = xscale1pmu_start,
+       .stop           = xscale1pmu_stop,
+       .cache_map      = &xscale_perf_cache_map,
+       .event_map      = &xscale_perf_map,
+       .raw_event_mask = 0xFF,
+       .num_events     = 3,
+       .max_period     = (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init xscale1pmu_init(void)
+{
+       return &xscale1pmu;
+}
+
+#define XSCALE2_OVERFLOWED_MASK        0x01f
+#define XSCALE2_CCOUNT_OVERFLOW        0x001
+#define XSCALE2_COUNT0_OVERFLOW        0x002
+#define XSCALE2_COUNT1_OVERFLOW        0x004
+#define XSCALE2_COUNT2_OVERFLOW        0x008
+#define XSCALE2_COUNT3_OVERFLOW        0x010
+#define XSCALE2_CCOUNT_INT_EN  0x001
+#define XSCALE2_COUNT0_INT_EN  0x002
+#define XSCALE2_COUNT1_INT_EN  0x004
+#define XSCALE2_COUNT2_INT_EN  0x008
+#define XSCALE2_COUNT3_INT_EN  0x010
+#define XSCALE2_COUNT0_EVT_SHFT        0
+#define XSCALE2_COUNT0_EVT_MASK        (0xff << XSCALE2_COUNT0_EVT_SHFT)
+#define XSCALE2_COUNT1_EVT_SHFT        8
+#define XSCALE2_COUNT1_EVT_MASK        (0xff << XSCALE2_COUNT1_EVT_SHFT)
+#define XSCALE2_COUNT2_EVT_SHFT        16
+#define XSCALE2_COUNT2_EVT_MASK        (0xff << XSCALE2_COUNT2_EVT_SHFT)
+#define XSCALE2_COUNT3_EVT_SHFT        24
+#define XSCALE2_COUNT3_EVT_MASK        (0xff << XSCALE2_COUNT3_EVT_SHFT)
+
+static inline u32
+xscale2pmu_read_pmnc(void)
+{
+       u32 val;
+       asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
+       /* bits 1-2 and 4-23 are read-unpredictable */
+       return val & 0xff000009;
+}
+
+static inline void
+xscale2pmu_write_pmnc(u32 val)
+{
+       /* bits 4-23 are write-as-0, 24-31 are write ignored */
+       val &= 0xf;
+       asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
+}
+
+static inline u32
+xscale2pmu_read_overflow_flags(void)
+{
+       u32 val;
+       asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
+       return val;
+}
+
+static inline void
+xscale2pmu_write_overflow_flags(u32 val)
+{
+       asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
+}
+
+static inline u32
+xscale2pmu_read_event_select(void)
+{
+       u32 val;
+       asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
+       return val;
+}
+
+static inline void
+xscale2pmu_write_event_select(u32 val)
+{
+       asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
+}
+
+static inline u32
+xscale2pmu_read_int_enable(void)
+{
+       u32 val;
+       asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
+       return val;
+}
+
+static void
+xscale2pmu_write_int_enable(u32 val)
+{
+       asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
+}
+
+static inline int
+xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
+                                       enum xscale_counters counter)
+{
+       int ret = 0;
+
+       switch (counter) {
+       case XSCALE_CYCLE_COUNTER:
+               ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
+               break;
+       case XSCALE_COUNTER0:
+               ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
+               break;
+       case XSCALE_COUNTER1:
+               ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
+               break;
+       case XSCALE_COUNTER2:
+               ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
+               break;
+       case XSCALE_COUNTER3:
+               ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
+               break;
+       default:
+               WARN_ONCE(1, "invalid counter number (%d)\n", counter);
+       }
+
+       return ret;
+}
+
+static irqreturn_t
+xscale2pmu_handle_irq(int irq_num, void *dev)
+{
+       unsigned long pmnc, of_flags;
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct pt_regs *regs;
+       int idx;
+
+       /* Disable the PMU. */
+       pmnc = xscale2pmu_read_pmnc();
+       xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
+
+       /* Check the overflow flag register. */
+       of_flags = xscale2pmu_read_overflow_flags();
+       if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
+               return IRQ_NONE;
+
+       /* Clear the overflow bits. */
+       xscale2pmu_write_overflow_flags(of_flags);
+
+       regs = get_irq_regs();
+
+       perf_sample_data_init(&data, 0);
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+       for (idx = 0; idx <= armpmu->num_events; ++idx) {
+               struct perf_event *event = cpuc->events[idx];
+               struct hw_perf_event *hwc;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
+                       continue;
+
+               hwc = &event->hw;
+               armpmu_event_update(event, hwc, idx);
+               data.period = event->hw.last_period;
+               if (!armpmu_event_set_period(event, hwc, idx))
+                       continue;
+
+               if (perf_event_overflow(event, 0, &data, regs))
+                       armpmu->disable(hwc, idx);
+       }
+
+       irq_work_run();
+
+       /*
+        * Re-enable the PMU.
+        */
+       pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
+       xscale2pmu_write_pmnc(pmnc);
+
+       return IRQ_HANDLED;
+}
+
+static void
+xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long flags, ien, evtsel;
+
+       ien = xscale2pmu_read_int_enable();
+       evtsel = xscale2pmu_read_event_select();
+
+       switch (idx) {
+       case XSCALE_CYCLE_COUNTER:
+               ien |= XSCALE2_CCOUNT_INT_EN;
+               break;
+       case XSCALE_COUNTER0:
+               ien |= XSCALE2_COUNT0_INT_EN;
+               evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
+               evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
+               break;
+       case XSCALE_COUNTER1:
+               ien |= XSCALE2_COUNT1_INT_EN;
+               evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
+               evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
+               break;
+       case XSCALE_COUNTER2:
+               ien |= XSCALE2_COUNT2_INT_EN;
+               evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
+               evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
+               break;
+       case XSCALE_COUNTER3:
+               ien |= XSCALE2_COUNT3_INT_EN;
+               evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
+               evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
+               break;
+       default:
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       xscale2pmu_write_event_select(evtsel);
+       xscale2pmu_write_int_enable(ien);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+       unsigned long flags, ien, evtsel;
+
+       ien = xscale2pmu_read_int_enable();
+       evtsel = xscale2pmu_read_event_select();
+
+       switch (idx) {
+       case XSCALE_CYCLE_COUNTER:
+               ien &= ~XSCALE2_CCOUNT_INT_EN;
+               break;
+       case XSCALE_COUNTER0:
+               ien &= ~XSCALE2_COUNT0_INT_EN;
+               evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
+               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
+               break;
+       case XSCALE_COUNTER1:
+               ien &= ~XSCALE2_COUNT1_INT_EN;
+               evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
+               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
+               break;
+       case XSCALE_COUNTER2:
+               ien &= ~XSCALE2_COUNT2_INT_EN;
+               evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
+               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
+               break;
+       case XSCALE_COUNTER3:
+               ien &= ~XSCALE2_COUNT3_INT_EN;
+               evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
+               evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
+               break;
+       default:
+               WARN_ONCE(1, "invalid counter number (%d)\n", idx);
+               return;
+       }
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       xscale2pmu_write_event_select(evtsel);
+       xscale2pmu_write_int_enable(ien);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static int
+xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
+                       struct hw_perf_event *event)
+{
+       int idx = xscale1pmu_get_event_idx(cpuc, event);
+       if (idx >= 0)
+               goto out;
+
+       if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
+               idx = XSCALE_COUNTER3;
+       else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
+               idx = XSCALE_COUNTER2;
+out:
+       return idx;
+}
+
+static void
+xscale2pmu_start(void)
+{
+       unsigned long flags, val;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
+       val |= XSCALE_PMU_ENABLE;
+       xscale2pmu_write_pmnc(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void
+xscale2pmu_stop(void)
+{
+       unsigned long flags, val;
+
+       raw_spin_lock_irqsave(&pmu_lock, flags);
+       val = xscale2pmu_read_pmnc();
+       val &= ~XSCALE_PMU_ENABLE;
+       xscale2pmu_write_pmnc(val);
+       raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static inline u32
+xscale2pmu_read_counter(int counter)
+{
+       u32 val = 0;
+
+       switch (counter) {
+       case XSCALE_CYCLE_COUNTER:
+               asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
+               break;
+       case XSCALE_COUNTER0:
+               asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
+               break;
+       case XSCALE_COUNTER1:
+               asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
+               break;
+       case XSCALE_COUNTER2:
+               asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
+               break;
+       case XSCALE_COUNTER3:
+               asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
+               break;
+       }
+
+       return val;
+}
+
+static inline void
+xscale2pmu_write_counter(int counter, u32 val)
+{
+       switch (counter) {
+       case XSCALE_CYCLE_COUNTER:
+               asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
+               break;
+       case XSCALE_COUNTER0:
+               asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
+               break;
+       case XSCALE_COUNTER1:
+               asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
+               break;
+       case XSCALE_COUNTER2:
+               asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
+               break;
+       case XSCALE_COUNTER3:
+               asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
+               break;
+       }
+}
+
+static const struct arm_pmu xscale2pmu = {
+       .id             = ARM_PERF_PMU_ID_XSCALE2,
+       .name           = "xscale2",
+       .handle_irq     = xscale2pmu_handle_irq,
+       .enable         = xscale2pmu_enable_event,
+       .disable        = xscale2pmu_disable_event,
+       .read_counter   = xscale2pmu_read_counter,
+       .write_counter  = xscale2pmu_write_counter,
+       .get_event_idx  = xscale2pmu_get_event_idx,
+       .start          = xscale2pmu_start,
+       .stop           = xscale2pmu_stop,
+       .cache_map      = &xscale_perf_cache_map,
+       .event_map      = &xscale_perf_map,
+       .raw_event_mask = 0xFF,
+       .num_events     = 5,
+       .max_period     = (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init xscale2pmu_init(void)
+{
+       return &xscale2pmu;
+}
+#else
+static const struct arm_pmu *__init xscale1pmu_init(void)
+{
+       return NULL;
+}
+
+static const struct arm_pmu *__init xscale2pmu_init(void)
+{
+       return NULL;
+}
+#endif /* CONFIG_CPU_XSCALE */
diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c
new file mode 100644 (file)
index 0000000..a4b1b07
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * linux/arch/arm/kernel/pj4-cp0.c
+ *
+ * PJ4 iWMMXt coprocessor context switching and handling
+ *
+ * Copyright (c) 2010 Marvell International Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/thread_notify.h>
+
+static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+       struct thread_info *thread = t;
+
+       switch (cmd) {
+       case THREAD_NOTIFY_FLUSH:
+               /*
+                * flush_thread() zeroes thread->fpstate, so no need
+                * to do anything here.
+                *
+                * FALLTHROUGH: Ensure we don't try to overwrite our newly
+                * initialised state information on the first fault.
+                */
+
+       case THREAD_NOTIFY_EXIT:
+               iwmmxt_task_release(thread);
+               break;
+
+       case THREAD_NOTIFY_SWITCH:
+               iwmmxt_task_switch(thread);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block iwmmxt_notifier_block = {
+       .notifier_call  = iwmmxt_do,
+};
+
+
+static u32 __init pj4_cp_access_read(void)
+{
+       u32 value;
+
+       __asm__ __volatile__ (
+               "mrc    p15, 0, %0, c1, c0, 2\n\t"
+               : "=r" (value));
+       return value;
+}
+
+static void __init pj4_cp_access_write(u32 value)
+{
+       u32 temp;
+
+       __asm__ __volatile__ (
+               "mcr    p15, 0, %1, c1, c0, 2\n\t"
+               "mrc    p15, 0, %0, c1, c0, 2\n\t"
+               "mov    %0, %0\n\t"
+               "sub    pc, pc, #4\n\t"
+               : "=r" (temp) : "r" (value));
+}
+
+
+/*
+ * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
+ * switch code handle iWMMXt context switching.
+ */
+static int __init pj4_cp0_init(void)
+{
+       u32 cp_access;
+
+       cp_access = pj4_cp_access_read() & ~0xf;
+       pj4_cp_access_write(cp_access);
+
+       printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n");
+       elf_hwcap |= HWCAP_IWMMXT;
+       thread_register_notifier(&iwmmxt_notifier_block);
+
+       return 0;
+}
+
+late_initcall(pj4_cp0_init);
index 3e97483abcf029ea15eee056d4fa400b2e170a34..19c6816db61ebe5bc92a7995c6ed76fa59bcd18c 100644 (file)
@@ -1060,8 +1060,8 @@ static int ptrace_sethbpregs(struct task_struct *tsk, long num,
                        goto out;
 
                if ((gen_type & implied_type) != gen_type) {
-                               ret = -EINVAL;
-                               goto out;
+                       ret = -EINVAL;
+                       goto out;
                }
 
                attr.bp_len     = gen_len;
index 8c1959590252e7161f1da38497eddba9b0538afb..bbca89872c18236a737c3ea8d963673821973676 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/cache.h>
 #include <linux/profile.h>
 #include <linux/errno.h>
+#include <linux/ftrace.h>
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/cpu.h>
@@ -457,7 +458,7 @@ static void ipi_timer(void)
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void __exception do_local_timer(struct pt_regs *regs)
+asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
        int cpu = smp_processor_id();
@@ -544,7 +545,7 @@ static void ipi_cpu_stop(unsigned int cpu)
  *
  *  Bit 0 - Inter-processor function call
  */
-asmlinkage void __exception do_IPI(struct pt_regs *regs)
+asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs)
 {
        unsigned int cpu = smp_processor_id();
        struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
index cead8893b46bc2d91ac156b9c8382c8aa4ebc71f..897c1a8f16942e179c9d42e3f4dd935542078762 100644 (file)
@@ -101,6 +101,7 @@ SECTIONS
                        __exception_text_start = .;
                        *(.exception.text)
                        __exception_text_end = .;
+                       IRQENTRY_TEXT
                        TEXT_TEXT
                        SCHED_TEXT
                        LOCK_TEXT
index 90fe9ab8591db4f7d96744328c7026ba47dd73df..08e5c8759502ba14cf3a83495ccd1df6d00dbf9b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
@@ -107,11 +108,64 @@ static void __init cns3420_early_serial_setup(void)
 #endif
 }
 
+/*
+ * USB
+ */
+static struct resource cns3xxx_usb_ehci_resources[] = {
+       [0] = {
+               .start = CNS3XXX_USB_BASE,
+               .end   = CNS3XXX_USB_BASE + SZ_16M - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_CNS3XXX_USB_EHCI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device cns3xxx_usb_ehci_device = {
+       .name          = "cns3xxx-ehci",
+       .num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources),
+       .resource      = cns3xxx_usb_ehci_resources,
+       .dev           = {
+               .dma_mask          = &cns3xxx_usb_ehci_dma_mask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+       },
+};
+
+static struct resource cns3xxx_usb_ohci_resources[] = {
+       [0] = {
+               .start = CNS3XXX_USB_OHCI_BASE,
+               .end   = CNS3XXX_USB_OHCI_BASE + SZ_16M - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_CNS3XXX_USB_OHCI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device cns3xxx_usb_ohci_device = {
+       .name          = "cns3xxx-ohci",
+       .num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources),
+       .resource      = cns3xxx_usb_ohci_resources,
+       .dev           = {
+               .dma_mask          = &cns3xxx_usb_ohci_dma_mask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+       },
+};
+
 /*
  * Initialization
  */
 static struct platform_device *cns3420_pdevs[] __initdata = {
        &cns3420_nor_pdev,
+       &cns3xxx_usb_ehci_device,
+       &cns3xxx_usb_ohci_device,
 };
 
 static void __init cns3420_init(void)
index 6b33ec11346e54b701fa61867804ecd1120d76e2..73898a7835d399abddfe4dad39d4f13eeb9e05d0 100644 (file)
@@ -17,7 +17,5 @@ extern struct sys_timer cns3xxx_timer;
 void __init cns3xxx_map_io(void);
 void __init cns3xxx_init_irq(void);
 void cns3xxx_power_off(void);
-void cns3xxx_pwr_power_up(unsigned int block);
-void cns3xxx_pwr_power_down(unsigned int block);
 
 #endif /* __CNS3XXX_CORE_H */
index 50b4d31c27c0f5d6ba08e4fcec406ad31fa06737..79d1fb02c23fdba10279d1e2e4af1d22220e5494 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
+#include <mach/pm.h>
 #include "core.h"
 #include "devices.h"
 
index 6dbce13771ca49c83c89dde5b4f0b6f734e20c1f..191c8e57f2890f09c30610bce584194bc1c3d7f1 100644 (file)
 #define CNS3XXX_USBOTG_BASE_VIRT               0xFFF15000
 
 #define CNS3XXX_USB_BASE                       0x82000000      /* USB Host Control */
-#define CNS3XXX_USB_BASE_VIRT                  0xFFF16000
 
 #define CNS3XXX_SATA2_BASE                     0x83000000      /* SATA */
 #define CNS3XXX_SATA2_SIZE                     SZ_16M
 #define CNS3XXX_2DG_BASE_VIRT                  0xFFF1B000
 
 #define CNS3XXX_USB_OHCI_BASE                  0x88000000      /* USB OHCI */
-#define CNS3XXX_USB_OHCI_BASE_VIRT             0xFFF1C000
 
 #define CNS3XXX_L2C_BASE                       0x92000000      /* L2 Cache Control */
 #define CNS3XXX_L2C_BASE_VIRT                  0xFFF27000
diff --git a/arch/arm/mach-cns3xxx/include/mach/pm.h b/arch/arm/mach-cns3xxx/include/mach/pm.h
new file mode 100644 (file)
index 0000000..6eae7f7
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000 Deep Blue Solutions Ltd
+ * Copyright 2004 ARM Limited
+ * Copyright 2008 Cavium Networks
+ *
+ * This file 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 __CNS3XXX_PM_H
+#define __CNS3XXX_PM_H
+
+#include <asm/atomic.h>
+
+void cns3xxx_pwr_clk_en(unsigned int block);
+void cns3xxx_pwr_clk_dis(unsigned int block);
+void cns3xxx_pwr_power_up(unsigned int block);
+void cns3xxx_pwr_power_down(unsigned int block);
+
+extern atomic_t usb_pwr_ref;
+
+#endif /* __CNS3XXX_PM_H */
index 38e44706feabf43a69a9a3429f3a6753b51d34a0..5e579552aa5444fb7189b8df54e09758fd912b56 100644 (file)
@@ -6,10 +6,14 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <asm/atomic.h>
 #include <mach/system.h>
 #include <mach/cns3xxx.h>
+#include <mach/pm.h>
 
 void cns3xxx_pwr_clk_en(unsigned int block)
 {
@@ -18,6 +22,16 @@ void cns3xxx_pwr_clk_en(unsigned int block)
        reg |= (block & PM_CLK_GATE_REG_MASK);
        __raw_writel(reg, PM_CLK_GATE_REG);
 }
+EXPORT_SYMBOL(cns3xxx_pwr_clk_en);
+
+void cns3xxx_pwr_clk_dis(unsigned int block)
+{
+       u32 reg = __raw_readl(PM_CLK_GATE_REG);
+
+       reg &= ~(block & PM_CLK_GATE_REG_MASK);
+       __raw_writel(reg, PM_CLK_GATE_REG);
+}
+EXPORT_SYMBOL(cns3xxx_pwr_clk_dis);
 
 void cns3xxx_pwr_power_up(unsigned int block)
 {
@@ -29,6 +43,7 @@ void cns3xxx_pwr_power_up(unsigned int block)
        /* Wait for 300us for the PLL output clock locked. */
        udelay(300);
 };
+EXPORT_SYMBOL(cns3xxx_pwr_power_up);
 
 void cns3xxx_pwr_power_down(unsigned int block)
 {
@@ -38,6 +53,7 @@ void cns3xxx_pwr_power_down(unsigned int block)
        reg |= (block & CNS3XXX_PWR_PLL_ALL);
        __raw_writel(reg, PM_PLL_HM_PD_CTRL_REG);
 };
+EXPORT_SYMBOL(cns3xxx_pwr_power_down);
 
 static void cns3xxx_pwr_soft_rst_force(unsigned int block)
 {
@@ -51,11 +67,13 @@ static void cns3xxx_pwr_soft_rst_force(unsigned int block)
                reg &= ~(block & PM_SOFT_RST_REG_MASK);
        } else {
                reg &= ~(block & PM_SOFT_RST_REG_MASK);
+               __raw_writel(reg, PM_SOFT_RST_REG);
                reg |= (block & PM_SOFT_RST_REG_MASK);
        }
 
        __raw_writel(reg, PM_SOFT_RST_REG);
 }
+EXPORT_SYMBOL(cns3xxx_pwr_soft_rst_force);
 
 void cns3xxx_pwr_soft_rst(unsigned int block)
 {
@@ -69,6 +87,7 @@ void cns3xxx_pwr_soft_rst(unsigned int block)
        }
        cns3xxx_pwr_soft_rst_force(block);
 }
+EXPORT_SYMBOL(cns3xxx_pwr_soft_rst);
 
 void arch_reset(char mode, const char *cmd)
 {
@@ -99,3 +118,7 @@ int cns3xxx_cpu_clock(void)
 
        return cpu;
 }
+EXPORT_SYMBOL(cns3xxx_cpu_clock);
+
+atomic_t usb_pwr_ref = ATOMIC_INIT(0);
+EXPORT_SYMBOL(usb_pwr_ref);
index b77b860b36d77a74d267e83d77e40427bbe4badf..32f147998cd9536b7daf47236da1b75e9029087f 100644 (file)
@@ -61,6 +61,8 @@ config MACH_DAVINCI_EVM
        bool "TI DM644x EVM"
        default ARCH_DAVINCI_DM644x
        depends on ARCH_DAVINCI_DM644x
+       select MISC_DEVICES
+       select EEPROM_AT24
        help
          Configure this option to specify the whether the board used
          for development is a DM644x EVM
@@ -68,6 +70,8 @@ config MACH_DAVINCI_EVM
 config MACH_SFFSDR
        bool "Lyrtech SFFSDR"
        depends on ARCH_DAVINCI_DM644x
+       select MISC_DEVICES
+       select EEPROM_AT24
        help
          Say Y here to select the Lyrtech Small Form Factor
          Software Defined Radio (SFFSDR) board.
@@ -99,6 +103,8 @@ config MACH_DAVINCI_DM6467_EVM
        default ARCH_DAVINCI_DM646x
        depends on ARCH_DAVINCI_DM646x
        select MACH_DAVINCI_DM6467TEVM
+       select MISC_DEVICES
+       select EEPROM_AT24
        help
          Configure this option to specify the whether the board used
          for development is a DM6467 EVM
@@ -110,6 +116,8 @@ config MACH_DAVINCI_DM365_EVM
        bool "TI DM365 EVM"
        default ARCH_DAVINCI_DM365
        depends on ARCH_DAVINCI_DM365
+       select MISC_DEVICES
+       select EEPROM_AT24
        help
          Configure this option to specify whether the board used
          for development is a DM365 EVM
@@ -119,6 +127,8 @@ config MACH_DAVINCI_DA830_EVM
        default ARCH_DAVINCI_DA830
        depends on ARCH_DAVINCI_DA830
        select GPIO_PCF857X
+       select MISC_DEVICES
+       select EEPROM_AT24
        help
          Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
 
@@ -148,7 +158,6 @@ config MACH_DAVINCI_DA850_EVM
        bool "TI DA850/OMAP-L138/AM18x Reference Platform"
        default ARCH_DAVINCI_DA850
        depends on ARCH_DAVINCI_DA850
-       select GPIO_PCA953X
        help
          Say Y here to select the TI DA850/OMAP-L138/AM18x Evaluation Module.
 
@@ -178,6 +187,12 @@ config DA850_UI_RMII
 
 endchoice
 
+config GPIO_PCA953X
+       default MACH_DAVINCI_DA850_EVM
+
+config KEYBOARD_GPIO_POLLED
+       default MACH_DAVINCI_DA850_EVM
+
 config MACH_TNETV107X
        bool "TI TNETV107X Reference Platform"
        default ARCH_DAVINCI_TNETV107X
@@ -188,6 +203,8 @@ config MACH_TNETV107X
 config MACH_MITYOMAPL138
        bool "Critical Link MityDSP-L138/MityARM-1808 SoM"
        depends on ARCH_DAVINCI_DA850
+       select MISC_DEVICES
+       select EEPROM_AT24
        help
          Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
          System on Module.  Information on this SoM may be found at
index 9c3f500fc12f3b1aacef4ee26002b6c4e56f1e65..1ce70a91f2e95bc5f6f44dc5d97a85a70f5bf028 100644 (file)
@@ -90,7 +90,7 @@ int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
                                        void __iomem *base, unsigned cs)
 {
        unsigned set, val;
-       unsigned ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
+       int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
        unsigned offset = A1CR_OFFSET + cs * 4;
        struct clk *aemif_clk;
        unsigned long clkrate;
index c6e11c682e4c31261abb6a0a6c1cb5141b3f60d8..b01fb2ab944a33d43414d231343cffd698ec7a2d 100644 (file)
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/input.h>
 #include <linux/mfd/tps6507x.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -266,34 +268,115 @@ static inline void da850_evm_setup_emac_rmii(int rmii_sel)
        struct davinci_soc_info *soc_info = &davinci_soc_info;
 
        soc_info->emac_pdata->rmii_en = 1;
-       gpio_set_value(rmii_sel, 0);
+       gpio_set_value_cansleep(rmii_sel, 0);
 }
 #else
 static inline void da850_evm_setup_emac_rmii(int rmii_sel) { }
 #endif
 
+
+#define DA850_KEYS_DEBOUNCE_MS 10
+/*
+ * At 200ms polling interval it is possible to miss an
+ * event by tapping very lightly on the push button but most
+ * pushes do result in an event; longer intervals require the
+ * user to hold the button whereas shorter intervals require
+ * more CPU time for polling.
+ */
+#define DA850_GPIO_KEYS_POLL_MS        200
+
+enum da850_evm_ui_exp_pins {
+       DA850_EVM_UI_EXP_SEL_C = 5,
+       DA850_EVM_UI_EXP_SEL_B,
+       DA850_EVM_UI_EXP_SEL_A,
+       DA850_EVM_UI_EXP_PB8,
+       DA850_EVM_UI_EXP_PB7,
+       DA850_EVM_UI_EXP_PB6,
+       DA850_EVM_UI_EXP_PB5,
+       DA850_EVM_UI_EXP_PB4,
+       DA850_EVM_UI_EXP_PB3,
+       DA850_EVM_UI_EXP_PB2,
+       DA850_EVM_UI_EXP_PB1,
+};
+
+static const char const *da850_evm_ui_exp[] = {
+       [DA850_EVM_UI_EXP_SEL_C]        = "sel_c",
+       [DA850_EVM_UI_EXP_SEL_B]        = "sel_b",
+       [DA850_EVM_UI_EXP_SEL_A]        = "sel_a",
+       [DA850_EVM_UI_EXP_PB8]          = "pb8",
+       [DA850_EVM_UI_EXP_PB7]          = "pb7",
+       [DA850_EVM_UI_EXP_PB6]          = "pb6",
+       [DA850_EVM_UI_EXP_PB5]          = "pb5",
+       [DA850_EVM_UI_EXP_PB4]          = "pb4",
+       [DA850_EVM_UI_EXP_PB3]          = "pb3",
+       [DA850_EVM_UI_EXP_PB2]          = "pb2",
+       [DA850_EVM_UI_EXP_PB1]          = "pb1",
+};
+
+#define DA850_N_UI_PB          8
+
+static struct gpio_keys_button da850_evm_ui_keys[] = {
+       [0 ... DA850_N_UI_PB - 1] = {
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 0,
+               .debounce_interval      = DA850_KEYS_DEBOUNCE_MS,
+               .code                   = -1, /* assigned at runtime */
+               .gpio                   = -1, /* assigned at runtime */
+               .desc                   = NULL, /* assigned at runtime */
+       },
+};
+
+static struct gpio_keys_platform_data da850_evm_ui_keys_pdata = {
+       .buttons = da850_evm_ui_keys,
+       .nbuttons = ARRAY_SIZE(da850_evm_ui_keys),
+       .poll_interval = DA850_GPIO_KEYS_POLL_MS,
+};
+
+static struct platform_device da850_evm_ui_keys_device = {
+       .name = "gpio-keys-polled",
+       .id = 0,
+       .dev = {
+               .platform_data = &da850_evm_ui_keys_pdata
+       },
+};
+
+static void da850_evm_ui_keys_init(unsigned gpio)
+{
+       int i;
+       struct gpio_keys_button *button;
+
+       for (i = 0; i < DA850_N_UI_PB; i++) {
+               button = &da850_evm_ui_keys[i];
+               button->code = KEY_F8 - i;
+               button->desc = (char *)
+                               da850_evm_ui_exp[DA850_EVM_UI_EXP_PB8 + i];
+               button->gpio = gpio + DA850_EVM_UI_EXP_PB8 + i;
+       }
+}
+
 static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
                                                unsigned ngpio, void *c)
 {
        int sel_a, sel_b, sel_c, ret;
 
-       sel_a = gpio + 7;
-       sel_b = gpio + 6;
-       sel_c = gpio + 5;
+       sel_a = gpio + DA850_EVM_UI_EXP_SEL_A;
+       sel_b = gpio + DA850_EVM_UI_EXP_SEL_B;
+       sel_c = gpio + DA850_EVM_UI_EXP_SEL_C;
 
-       ret = gpio_request(sel_a, "sel_a");
+       ret = gpio_request(sel_a, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_A]);
        if (ret) {
                pr_warning("Cannot open UI expander pin %d\n", sel_a);
                goto exp_setup_sela_fail;
        }
 
-       ret = gpio_request(sel_b, "sel_b");
+       ret = gpio_request(sel_b, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_B]);
        if (ret) {
                pr_warning("Cannot open UI expander pin %d\n", sel_b);
                goto exp_setup_selb_fail;
        }
 
-       ret = gpio_request(sel_c, "sel_c");
+       ret = gpio_request(sel_c, da850_evm_ui_exp[DA850_EVM_UI_EXP_SEL_C]);
        if (ret) {
                pr_warning("Cannot open UI expander pin %d\n", sel_c);
                goto exp_setup_selc_fail;
@@ -304,6 +387,13 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
        gpio_direction_output(sel_b, 1);
        gpio_direction_output(sel_c, 1);
 
+       da850_evm_ui_keys_init(gpio);
+       ret = platform_device_register(&da850_evm_ui_keys_device);
+       if (ret) {
+               pr_warning("Could not register UI GPIO expander push-buttons");
+               goto exp_setup_keys_fail;
+       }
+
        ui_card_detected = 1;
        pr_info("DA850/OMAP-L138 EVM UI card detected\n");
 
@@ -313,6 +403,8 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
 
        return 0;
 
+exp_setup_keys_fail:
+       gpio_free(sel_c);
 exp_setup_selc_fail:
        gpio_free(sel_b);
 exp_setup_selb_fail:
@@ -324,14 +416,192 @@ exp_setup_sela_fail:
 static int da850_evm_ui_expander_teardown(struct i2c_client *client,
                                        unsigned gpio, unsigned ngpio, void *c)
 {
+       platform_device_unregister(&da850_evm_ui_keys_device);
+
        /* deselect all functionalities */
-       gpio_set_value(gpio + 5, 1);
-       gpio_set_value(gpio + 6, 1);
-       gpio_set_value(gpio + 7, 1);
+       gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_C, 1);
+       gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_B, 1);
+       gpio_set_value_cansleep(gpio + DA850_EVM_UI_EXP_SEL_A, 1);
+
+       gpio_free(gpio + DA850_EVM_UI_EXP_SEL_C);
+       gpio_free(gpio + DA850_EVM_UI_EXP_SEL_B);
+       gpio_free(gpio + DA850_EVM_UI_EXP_SEL_A);
+
+       return 0;
+}
+
+/* assign the baseboard expander's GPIOs after the UI board's */
+#define DA850_UI_EXPANDER_N_GPIOS ARRAY_SIZE(da850_evm_ui_exp)
+#define DA850_BB_EXPANDER_GPIO_BASE (DAVINCI_N_GPIO + DA850_UI_EXPANDER_N_GPIOS)
+
+enum da850_evm_bb_exp_pins {
+       DA850_EVM_BB_EXP_DEEP_SLEEP_EN = 0,
+       DA850_EVM_BB_EXP_SW_RST,
+       DA850_EVM_BB_EXP_TP_23,
+       DA850_EVM_BB_EXP_TP_22,
+       DA850_EVM_BB_EXP_TP_21,
+       DA850_EVM_BB_EXP_USER_PB1,
+       DA850_EVM_BB_EXP_USER_LED2,
+       DA850_EVM_BB_EXP_USER_LED1,
+       DA850_EVM_BB_EXP_USER_SW1,
+       DA850_EVM_BB_EXP_USER_SW2,
+       DA850_EVM_BB_EXP_USER_SW3,
+       DA850_EVM_BB_EXP_USER_SW4,
+       DA850_EVM_BB_EXP_USER_SW5,
+       DA850_EVM_BB_EXP_USER_SW6,
+       DA850_EVM_BB_EXP_USER_SW7,
+       DA850_EVM_BB_EXP_USER_SW8
+};
+
+static const char const *da850_evm_bb_exp[] = {
+       [DA850_EVM_BB_EXP_DEEP_SLEEP_EN]        = "deep_sleep_en",
+       [DA850_EVM_BB_EXP_SW_RST]               = "sw_rst",
+       [DA850_EVM_BB_EXP_TP_23]                = "tp_23",
+       [DA850_EVM_BB_EXP_TP_22]                = "tp_22",
+       [DA850_EVM_BB_EXP_TP_21]                = "tp_21",
+       [DA850_EVM_BB_EXP_USER_PB1]             = "user_pb1",
+       [DA850_EVM_BB_EXP_USER_LED2]            = "user_led2",
+       [DA850_EVM_BB_EXP_USER_LED1]            = "user_led1",
+       [DA850_EVM_BB_EXP_USER_SW1]             = "user_sw1",
+       [DA850_EVM_BB_EXP_USER_SW2]             = "user_sw2",
+       [DA850_EVM_BB_EXP_USER_SW3]             = "user_sw3",
+       [DA850_EVM_BB_EXP_USER_SW4]             = "user_sw4",
+       [DA850_EVM_BB_EXP_USER_SW5]             = "user_sw5",
+       [DA850_EVM_BB_EXP_USER_SW6]             = "user_sw6",
+       [DA850_EVM_BB_EXP_USER_SW7]             = "user_sw7",
+       [DA850_EVM_BB_EXP_USER_SW8]             = "user_sw8",
+};
+
+#define DA850_N_BB_USER_SW     8
+
+static struct gpio_keys_button da850_evm_bb_keys[] = {
+       [0] = {
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 0,
+               .debounce_interval      = DA850_KEYS_DEBOUNCE_MS,
+               .code                   = KEY_PROG1,
+               .desc                   = NULL, /* assigned at runtime */
+               .gpio                   = -1, /* assigned at runtime */
+       },
+       [1 ... DA850_N_BB_USER_SW] = {
+               .type                   = EV_SW,
+               .active_low             = 1,
+               .wakeup                 = 0,
+               .debounce_interval      = DA850_KEYS_DEBOUNCE_MS,
+               .code                   = -1, /* assigned at runtime */
+               .desc                   = NULL, /* assigned at runtime */
+               .gpio                   = -1, /* assigned at runtime */
+       },
+};
+
+static struct gpio_keys_platform_data da850_evm_bb_keys_pdata = {
+       .buttons = da850_evm_bb_keys,
+       .nbuttons = ARRAY_SIZE(da850_evm_bb_keys),
+       .poll_interval = DA850_GPIO_KEYS_POLL_MS,
+};
+
+static struct platform_device da850_evm_bb_keys_device = {
+       .name = "gpio-keys-polled",
+       .id = 1,
+       .dev = {
+               .platform_data = &da850_evm_bb_keys_pdata
+       },
+};
+
+static void da850_evm_bb_keys_init(unsigned gpio)
+{
+       int i;
+       struct gpio_keys_button *button;
+
+       button = &da850_evm_bb_keys[0];
+       button->desc = (char *)
+               da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_PB1];
+       button->gpio = gpio + DA850_EVM_BB_EXP_USER_PB1;
+
+       for (i = 0; i < DA850_N_BB_USER_SW; i++) {
+               button = &da850_evm_bb_keys[i + 1];
+               button->code = SW_LID + i;
+               button->desc = (char *)
+                               da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_SW1 + i];
+               button->gpio = gpio + DA850_EVM_BB_EXP_USER_SW1 + i;
+       }
+}
 
-       gpio_free(gpio + 5);
-       gpio_free(gpio + 6);
-       gpio_free(gpio + 7);
+#define DA850_N_BB_USER_LED    2
+
+static struct gpio_led da850_evm_bb_leds[] = {
+       [0 ... DA850_N_BB_USER_LED - 1] = {
+               .active_low = 1,
+               .gpio = -1, /* assigned at runtime */
+               .name = NULL, /* assigned at runtime */
+       },
+};
+
+static struct gpio_led_platform_data da850_evm_bb_leds_pdata = {
+       .leds = da850_evm_bb_leds,
+       .num_leds = ARRAY_SIZE(da850_evm_bb_leds),
+};
+
+static struct platform_device da850_evm_bb_leds_device = {
+       .name           = "leds-gpio",
+       .id             = -1,
+       .dev = {
+               .platform_data = &da850_evm_bb_leds_pdata
+       }
+};
+
+static void da850_evm_bb_leds_init(unsigned gpio)
+{
+       int i;
+       struct gpio_led *led;
+
+       for (i = 0; i < DA850_N_BB_USER_LED; i++) {
+               led = &da850_evm_bb_leds[i];
+
+               led->gpio = gpio + DA850_EVM_BB_EXP_USER_LED2 + i;
+               led->name =
+                       da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_LED2 + i];
+       }
+}
+
+static int da850_evm_bb_expander_setup(struct i2c_client *client,
+                                               unsigned gpio, unsigned ngpio,
+                                               void *c)
+{
+       int ret;
+
+       /*
+        * Register the switches and pushbutton on the baseboard as a gpio-keys
+        * device.
+        */
+       da850_evm_bb_keys_init(gpio);
+       ret = platform_device_register(&da850_evm_bb_keys_device);
+       if (ret) {
+               pr_warning("Could not register baseboard GPIO expander keys");
+               goto io_exp_setup_sw_fail;
+       }
+
+       da850_evm_bb_leds_init(gpio);
+       ret = platform_device_register(&da850_evm_bb_leds_device);
+       if (ret) {
+               pr_warning("Could not register baseboard GPIO expander LEDS");
+               goto io_exp_setup_leds_fail;
+       }
+
+       return 0;
+
+io_exp_setup_leds_fail:
+       platform_device_unregister(&da850_evm_bb_keys_device);
+io_exp_setup_sw_fail:
+       return ret;
+}
+
+static int da850_evm_bb_expander_teardown(struct i2c_client *client,
+                                       unsigned gpio, unsigned ngpio, void *c)
+{
+       platform_device_unregister(&da850_evm_bb_leds_device);
+       platform_device_unregister(&da850_evm_bb_keys_device);
 
        return 0;
 }
@@ -340,6 +610,14 @@ static struct pca953x_platform_data da850_evm_ui_expander_info = {
        .gpio_base      = DAVINCI_N_GPIO,
        .setup          = da850_evm_ui_expander_setup,
        .teardown       = da850_evm_ui_expander_teardown,
+       .names          = da850_evm_ui_exp,
+};
+
+static struct pca953x_platform_data da850_evm_bb_expander_info = {
+       .gpio_base      = DA850_BB_EXPANDER_GPIO_BASE,
+       .setup          = da850_evm_bb_expander_setup,
+       .teardown       = da850_evm_bb_expander_teardown,
+       .names          = da850_evm_bb_exp,
 };
 
 static struct i2c_board_info __initdata da850_evm_i2c_devices[] = {
@@ -350,6 +628,10 @@ static struct i2c_board_info __initdata da850_evm_i2c_devices[] = {
                I2C_BOARD_INFO("tca6416", 0x20),
                .platform_data = &da850_evm_ui_expander_info,
        },
+       {
+               I2C_BOARD_INFO("tca6416", 0x21),
+               .platform_data = &da850_evm_bb_expander_info,
+       },
 };
 
 static struct davinci_i2c_platform_data da850_evm_i2c_0_pdata = {
@@ -540,7 +822,7 @@ static struct regulator_init_data tps65070_regulator_data[] = {
        {
                .constraints = {
                        .min_uV = 950000,
-                       .max_uV = 1320000,
+                       .max_uV = 1350000,
                        .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE |
                                REGULATOR_CHANGE_STATUS),
                        .boot_on = 1,
@@ -591,7 +873,7 @@ static struct tps6507x_board tps_board = {
        .tps6507x_ts_init_data = &tps6507x_touchscreen_data,
 };
 
-static struct i2c_board_info __initdata da850evm_tps65070_info[] = {
+static struct i2c_board_info __initdata da850_evm_tps65070_info[] = {
        {
                I2C_BOARD_INFO("tps6507x", 0x48),
                .platform_data = &tps_board,
@@ -600,8 +882,8 @@ static struct i2c_board_info __initdata da850evm_tps65070_info[] = {
 
 static int __init pmic_tps65070_init(void)
 {
-       return i2c_register_board_info(1, da850evm_tps65070_info,
-                                       ARRAY_SIZE(da850evm_tps65070_info));
+       return i2c_register_board_info(1, da850_evm_tps65070_info,
+                                       ARRAY_SIZE(da850_evm_tps65070_info));
 }
 
 static const short da850_evm_lcdc_pins[] = {
@@ -736,6 +1018,27 @@ static struct edma_rsv_info *da850_edma_rsv[2] = {
        &da850_edma_cc1_rsv,
 };
 
+#ifdef CONFIG_CPU_FREQ
+static __init int da850_evm_init_cpufreq(void)
+{
+       switch (system_rev & 0xF) {
+       case 3:
+               da850_max_speed = 456000;
+               break;
+       case 2:
+               da850_max_speed = 408000;
+               break;
+       case 1:
+               da850_max_speed = 372000;
+               break;
+       }
+
+       return da850_register_cpufreq("pll0_sysclk3");
+}
+#else
+static __init int da850_evm_init_cpufreq(void) { return 0; }
+#endif
+
 static __init void da850_evm_init(void)
 {
        int ret;
@@ -836,7 +1139,7 @@ static __init void da850_evm_init(void)
        if (ret)
                pr_warning("da850_evm_init: rtc setup failed: %d\n", ret);
 
-       ret = da850_register_cpufreq("pll0_sysclk3");
+       ret = da850_evm_init_cpufreq();
        if (ret)
                pr_warning("da850_evm_init: cpufreq registration failed: %d\n",
                                ret);
index 01ba080433db556d0364cadb791303d2433b69a3..e4e3af179f0270e0c60698b66ed27eb321023b82 100644 (file)
@@ -336,7 +336,7 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate)
                ratio--;
        }
 
-       if (ratio > PLLDIV_RATIO_MASK)
+       if (ratio > pll->div_ratio_mask)
                return -EINVAL;
 
        do {
@@ -344,7 +344,7 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate)
        } while (v & PLLSTAT_GOSTAT);
 
        v = __raw_readl(pll->base + clk->div_reg);
-       v &= ~PLLDIV_RATIO_MASK;
+       v &= ~pll->div_ratio_mask;
        v |= ratio | PLLDIV_EN;
        __raw_writel(v, pll->base + clk->div_reg);
 
index 63916b90276042f01750bf5a41f79d7b64c2fd3a..78b5ae29ae403688c9ed82077f460bdb9c4647ac 100644 (file)
@@ -830,8 +830,7 @@ static void da850_set_async3_src(int pllnum)
  * According to the TRM, minimum PLLM results in maximum power savings.
  * The OPP definitions below should keep the PLLM as low as possible.
  *
- * The output of the PLLM must be between 400 to 600 MHz.
- * This rules out prediv of anything but divide-by-one for 24Mhz OSC input.
+ * The output of the PLLM must be between 300 to 600 MHz.
  */
 struct da850_opp {
        unsigned int    freq;   /* in KHz */
@@ -842,6 +841,33 @@ struct da850_opp {
        unsigned int    cvdd_max; /* in uV */
 };
 
+static const struct da850_opp da850_opp_456 = {
+       .freq           = 456000,
+       .prediv         = 1,
+       .mult           = 19,
+       .postdiv        = 1,
+       .cvdd_min       = 1300000,
+       .cvdd_max       = 1350000,
+};
+
+static const struct da850_opp da850_opp_408 = {
+       .freq           = 408000,
+       .prediv         = 1,
+       .mult           = 17,
+       .postdiv        = 1,
+       .cvdd_min       = 1300000,
+       .cvdd_max       = 1350000,
+};
+
+static const struct da850_opp da850_opp_372 = {
+       .freq           = 372000,
+       .prediv         = 2,
+       .mult           = 31,
+       .postdiv        = 1,
+       .cvdd_min       = 1200000,
+       .cvdd_max       = 1320000,
+};
+
 static const struct da850_opp da850_opp_300 = {
        .freq           = 300000,
        .prediv         = 1,
@@ -876,6 +902,9 @@ static const struct da850_opp da850_opp_96 = {
        }
 
 static struct cpufreq_frequency_table da850_freq_table[] = {
+       OPP(456),
+       OPP(408),
+       OPP(372),
        OPP(300),
        OPP(200),
        OPP(96),
@@ -885,6 +914,19 @@ static struct cpufreq_frequency_table da850_freq_table[] = {
        },
 };
 
+#ifdef CONFIG_REGULATOR
+static int da850_set_voltage(unsigned int index);
+static int da850_regulator_init(void);
+#endif
+
+static struct davinci_cpufreq_config cpufreq_info = {
+       .freq_table = da850_freq_table,
+#ifdef CONFIG_REGULATOR
+       .init = da850_regulator_init,
+       .set_voltage = da850_set_voltage,
+#endif
+};
+
 #ifdef CONFIG_REGULATOR
 static struct regulator *cvdd;
 
@@ -895,7 +937,7 @@ static int da850_set_voltage(unsigned int index)
        if (!cvdd)
                return -ENODEV;
 
-       opp = (struct da850_opp *) da850_freq_table[index].index;
+       opp = (struct da850_opp *) cpufreq_info.freq_table[index].index;
 
        return regulator_set_voltage(cvdd, opp->cvdd_min, opp->cvdd_max);
 }
@@ -912,14 +954,6 @@ static int da850_regulator_init(void)
 }
 #endif
 
-static struct davinci_cpufreq_config cpufreq_info = {
-       .freq_table = &da850_freq_table[0],
-#ifdef CONFIG_REGULATOR
-       .init = da850_regulator_init,
-       .set_voltage = da850_set_voltage,
-#endif
-};
-
 static struct platform_device da850_cpufreq_device = {
        .name                   = "cpufreq-davinci",
        .dev = {
@@ -928,12 +962,22 @@ static struct platform_device da850_cpufreq_device = {
        .id = -1,
 };
 
+unsigned int da850_max_speed = 300000;
+
 int __init da850_register_cpufreq(char *async_clk)
 {
+       int i;
+
        /* cpufreq driver can help keep an "async" clock constant */
        if (async_clk)
                clk_add_alias("async", da850_cpufreq_device.name,
                                                        async_clk, NULL);
+       for (i = 0; i < ARRAY_SIZE(da850_freq_table); i++) {
+               if (da850_freq_table[i].frequency <= da850_max_speed) {
+                       cpufreq_info.freq_table = &da850_freq_table[i];
+                       break;
+               }
+       }
 
        return platform_device_register(&da850_cpufreq_device);
 }
@@ -942,17 +986,18 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate)
 {
        int i, ret = 0, diff;
        unsigned int best = (unsigned int) -1;
+       struct cpufreq_frequency_table *table = cpufreq_info.freq_table;
 
        rate /= 1000; /* convert to kHz */
 
-       for (i = 0; da850_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-               diff = da850_freq_table[i].frequency - rate;
+       for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
+               diff = table[i].frequency - rate;
                if (diff < 0)
                        diff = -diff;
 
                if (diff < best) {
                        best = diff;
-                       ret = da850_freq_table[i].frequency;
+                       ret = table[i].frequency;
                }
        }
 
@@ -973,7 +1018,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
        struct pll_data *pll = clk->pll_data;
        int ret;
 
-       opp = (struct da850_opp *) da850_freq_table[index].index;
+       opp = (struct da850_opp *) cpufreq_info.freq_table[index].index;
        prediv = opp->prediv;
        mult = opp->mult;
        postdiv = opp->postdiv;
index c9a86d8130d151795433d7833b2fb85911a2bec5..85503debda51084090010b57f212b28b8e5b397c 100644 (file)
@@ -344,7 +344,20 @@ static struct platform_device tsc_device = {
 
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
-       int i;
+       int i, error;
+       struct clk *tsc_clk;
+
+       /*
+        * The reset defaults for tnetv107x tsc clock divider is set too high.
+        * This forces the clock down to a range that allows the ADC to
+        * complete sample conversion in time.
+        */
+       tsc_clk = clk_get(NULL, "sys_tsc_clk");
+       if (tsc_clk) {
+               error = clk_set_rate(tsc_clk, 5000000);
+               WARN_ON(error < 0);
+               clk_put(tsc_clk);
+       }
 
        platform_device_register(&edma_device);
        platform_device_register(&tnetv107x_wdt_device);
index 4247b3f53b338f596b37fc1664becc3c82df727e..e7f95206652763b1aabf85644a78a1f3c52f8395 100644 (file)
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
 
+/*
+ * If the DA850/OMAP-L138/AM18x SoC on board is of a higher speed grade
+ * (than the regular 300Mhz variant), the board code should set this up
+ * with the supported speed before calling da850_register_cpufreq().
+ */
+extern unsigned int da850_max_speed;
+
 /*
  * The cp_intc interrupt controller for the da8xx isn't in the same
  * chunk of physical memory space as the other registers (like it is
index 1b15dbd0a77be4492954e262f05a7af80e3beb50..a415804007017171d8c01b64f22d58b8fe17bc33 100644 (file)
@@ -83,20 +83,15 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,
                pdctl1 = __raw_readl(psc_base + PDCTL1);
                pdctl1 |= 0x100;
                __raw_writel(pdctl1, psc_base + PDCTL1);
-
-               do {
-                       ptstat = __raw_readl(psc_base +
-                                              PTSTAT);
-               } while (!(((ptstat >> domain) & 1) == 0));
        } else {
                ptcmd = 1 << domain;
                __raw_writel(ptcmd, psc_base + PTCMD);
-
-               do {
-                       ptstat = __raw_readl(psc_base + PTSTAT);
-               } while (!(((ptstat >> domain) & 1) == 0));
        }
 
+       do {
+               ptstat = __raw_readl(psc_base + PTSTAT);
+       } while (!(((ptstat >> domain) & 1) == 0));
+
        do {
                mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
        } while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
index 0f21c36e65dd4c33e02aa8017f1d04e24f237c6f..5d1eea026635cb18d3f7e7d595c1b182de21eb20 100644 (file)
@@ -272,14 +272,35 @@ static cycle_t read_cycles(struct clocksource *cs)
        return (cycles_t)timer32_read(t);
 }
 
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t read_dummy(struct clocksource *cs)
+{
+       return 0;
+}
+
+
 static struct clocksource clocksource_davinci = {
        .rating         = 300,
-       .read           = read_cycles,
+       .read           = read_dummy,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 24,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+/*
+ * Overwrite weak default sched_clock with something more precise
+ */
+unsigned long long notrace sched_clock(void)
+{
+       const cycle_t cyc = clocksource_davinci.read(&clocksource_davinci);
+
+       return clocksource_cyc2ns(cyc, clocksource_davinci.mult,
+                               clocksource_davinci.shift);
+}
+
 /*
  * clockevent
  */
@@ -377,6 +398,7 @@ static void __init davinci_timer_init(void)
        davinci_clock_tick_rate = clk_get_rate(timer_clk);
 
        /* setup clocksource */
+       clocksource_davinci.read = read_cycles;
        clocksource_davinci.name = id_to_name[clocksource_id];
        clocksource_davinci.mult =
                clocksource_khz2mult(davinci_clock_tick_rate/1000,
index daeae06430b9093417011fc9f3ece612adcf8ee4..6fcdecec8d8c387ba63c144046748fa02b469dc8 100644 (file)
@@ -131,12 +131,13 @@ define_pll_clk(tdm, 1, 0x0ff, 0x200);
 define_pll_clk(eth, 2, 0x0ff, 0x400);
 
 /* Level 2 - divided outputs from the PLLs */
-#define define_pll_div_clk(pll, cname, div)            \
-       static struct clk pll##_##cname##_clk = {       \
-               .name           = #pll "_" #cname "_clk",\
-               .parent         = &pll_##pll##_clk,     \
-               .flags          = CLK_PLL,              \
-               .div_reg        = PLLDIV##div,          \
+#define define_pll_div_clk(pll, cname, div)                    \
+       static struct clk pll##_##cname##_clk = {               \
+               .name           = #pll "_" #cname "_clk",       \
+               .parent         = &pll_##pll##_clk,             \
+               .flags          = CLK_PLL,                      \
+               .div_reg        = PLLDIV##div,                  \
+               .set_rate       = davinci_set_sysclk_rate,      \
        }
 
 define_pll_div_clk(sys, arm1176,       1);
@@ -192,6 +193,7 @@ lpsc_clk_enabled(system,    sys_half_clk,   SYSTEM);
 lpsc_clk_enabled(ddr2_vrst,    sys_ddr_clk,    DDR2_EMIF1_VRST);
 lpsc_clk_enabled(ddr2_vctl_rst,        sys_ddr_clk,    DDR2_EMIF2_VCTL_RST);
 lpsc_clk_enabled(wdt_arm,      sys_half_clk,   WDT_ARM);
+lpsc_clk_enabled(timer1,       sys_half_clk,   TIMER1);
 
 lpsc_clk(mbx_lite,     sys_arm1176_clk,        MBX_LITE);
 lpsc_clk(ethss,                eth_125mhz_clk,         ETHSS);
@@ -205,16 +207,15 @@ lpsc_clk(mdio,            sys_half_clk,           MDIO);
 lpsc_clk(sdio0,                sys_half_clk,           SDIO0);
 lpsc_clk(sdio1,                sys_half_clk,           SDIO1);
 lpsc_clk(timer0,       sys_half_clk,           TIMER0);
-lpsc_clk(timer1,       sys_half_clk,           TIMER1);
 lpsc_clk(wdt_dsp,      sys_half_clk,           WDT_DSP);
 lpsc_clk(ssp,          sys_half_clk,           SSP);
 lpsc_clk(tdm0,         tdm_0_clk,              TDM0);
 lpsc_clk(tdm1,         tdm_1_clk,              TDM1);
 lpsc_clk(vlynq,                sys_vlynq_ref_clk,      VLYNQ);
 lpsc_clk(mcdma,                sys_half_clk,           MCDMA);
-lpsc_clk(usb0,         sys_half_clk,           USB0);
-lpsc_clk(usb1,         sys_half_clk,           USB1);
 lpsc_clk(usbss,                sys_half_clk,           USBSS);
+lpsc_clk(usb0,         clk_usbss,              USB0);
+lpsc_clk(usb1,         clk_usbss,              USB1);
 lpsc_clk(ethss_rgmii,  eth_250mhz_clk,         ETHSS_RGMII);
 lpsc_clk(imcop,                sys_dsp_clk,            IMCOP);
 lpsc_clk(spare,                sys_half_clk,           SPARE);
@@ -281,7 +282,9 @@ static struct clk_lookup clks[] = {
        CLK(NULL,               "clk_tdm0",             &clk_tdm0),
        CLK(NULL,               "clk_vlynq",            &clk_vlynq),
        CLK(NULL,               "clk_mcdma",            &clk_mcdma),
+       CLK(NULL,               "clk_usbss",            &clk_usbss),
        CLK(NULL,               "clk_usb0",             &clk_usb0),
+       CLK(NULL,               "clk_usb1",             &clk_usb1),
        CLK(NULL,               "clk_tdm1",             &clk_tdm1),
        CLK(NULL,               "clk_debugss",          &clk_debugss),
        CLK(NULL,               "clk_ethss_rgmii",      &clk_ethss_rgmii),
@@ -289,8 +292,6 @@ static struct clk_lookup clks[] = {
        CLK(NULL,               "clk_imcop",            &clk_imcop),
        CLK(NULL,               "clk_spare",            &clk_spare),
        CLK("davinci_mmc.1",    NULL,                   &clk_sdio1),
-       CLK(NULL,               "clk_usb1",             &clk_usb1),
-       CLK(NULL,               "clk_usbss",            &clk_usbss),
        CLK(NULL,               "clk_ddr2_vrst",        &clk_ddr2_vrst),
        CLK(NULL,               "clk_ddr2_vctl_rst",    &clk_ddr2_vctl_rst),
        CLK(NULL,               NULL,                   NULL),
index 3b9a32ace90958562547b46d490a1f7b86674d3a..a4ed3900912af08130001a3a5cbc4169f4a96b63 100644 (file)
@@ -9,6 +9,12 @@ config MACH_DOVE_DB
          Say 'Y' here if you want your kernel to support the
          Marvell DB-MV88AP510 Development Board.
 
+ config MACH_CM_A510
+       bool "CompuLab CM-A510 Board"
+       help
+         Say 'Y' here if you want your kernel to support the
+         CompuLab CM-A510 Board.
+
 endmenu
 
 endif
index 7ab3be53f642b98d1a8ac9947f5b463372e4b451..fa0f018560600b0e4a3d335240e805db4b482d7c 100644 (file)
@@ -1,3 +1,4 @@
-obj-y                          += common.o addr-map.o irq.o pcie.o
+obj-y                          += common.o addr-map.o irq.o pcie.o mpp.o
 
 obj-$(CONFIG_MACH_DOVE_DB)     += dove-db-setup.o
+obj-$(CONFIG_MACH_CM_A510)     += cm-a510.o
diff --git a/arch/arm/mach-dove/cm-a510.c b/arch/arm/mach-dove/cm-a510.c
new file mode 100644 (file)
index 0000000..96e0e94
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * arch/arm/mach-dove/cm-a510.c
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Konstantin Sinyuk <kostyas@compulab.co.il>
+ *
+ * Based on Marvell DB-MV88AP510-BP Development Board Setup
+ *
+ * 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/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/dove.h>
+
+#include "common.h"
+
+static struct mv643xx_eth_platform_data cm_a510_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR_DEFAULT,
+};
+
+static struct mv_sata_platform_data cm_a510_sata_data = {
+       .n_ports        = 1,
+};
+
+/*
+ * SPI Devices:
+ * SPI0: 1M Flash Winbond w25q32bv
+ */
+static const struct flash_platform_data cm_a510_spi_flash_data = {
+       .type           = "w25q32bv",
+};
+
+static struct spi_board_info __initdata cm_a510_spi_flash_info[] = {
+       {
+               .modalias       = "m25p80",
+               .platform_data  = &cm_a510_spi_flash_data,
+               .irq            = -1,
+               .max_speed_hz   = 20000000,
+               .bus_num        = 0,
+               .chip_select    = 0,
+       },
+};
+
+static int __init cm_a510_pci_init(void)
+{
+       if (machine_is_cm_a510())
+               dove_pcie_init(1, 1);
+
+       return 0;
+}
+
+subsys_initcall(cm_a510_pci_init);
+
+/* Board Init */
+static void __init cm_a510_init(void)
+{
+       /*
+        * Basic Dove setup. Needs to be called early.
+        */
+       dove_init();
+
+       dove_ge00_init(&cm_a510_ge00_data);
+       dove_ehci0_init();
+       dove_ehci1_init();
+       dove_sata_init(&cm_a510_sata_data);
+       dove_sdio0_init();
+       dove_sdio1_init();
+       dove_spi0_init();
+       dove_spi1_init();
+       dove_uart0_init();
+       dove_uart1_init();
+       dove_i2c_init();
+       spi_register_board_info(cm_a510_spi_flash_info,
+                               ARRAY_SIZE(cm_a510_spi_flash_info));
+}
+
+MACHINE_START(CM_A510, "Compulab CM-A510 Board")
+       .boot_params    = 0x00000100,
+       .init_machine   = cm_a510_init,
+       .map_io         = dove_map_io,
+       .init_irq       = dove_init_irq,
+       .timer          = &dove_timer,
+MACHINE_END
index f6a08397f046b70bc48f60edd466b1ec1867bfa9..27b414578f2efff7715d33f13892371778e2864d 100644 (file)
 #define DOVE_RESET_SAMPLE_LO   (DOVE_MPP_VIRT_BASE | 0x014)
 #define DOVE_RESET_SAMPLE_HI   (DOVE_MPP_VIRT_BASE | 0x018)
 #define DOVE_GPIO_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe8400)
 #define DOVE_MPP_GENERAL_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE | 0xe803c)
 #define  DOVE_AU1_SPDIFO_GPIO_EN       (1 << 1)
 #define  DOVE_NAND_GPIO_EN             (1 << 0)
 #define DOVE_MPP_CTRL4_VIRT_BASE       (DOVE_GPIO_VIRT_BASE + 0x40)
-
+#define  DOVE_SPI_GPIO_SEL             (1 << 5)
+#define  DOVE_UART1_GPIO_SEL           (1 << 4)
+#define  DOVE_AU1_GPIO_SEL             (1 << 3)
+#define  DOVE_CAM_GPIO_SEL             (1 << 2)
+#define  DOVE_SD1_GPIO_SEL             (1 << 1)
+#define  DOVE_SD0_GPIO_SEL             (1 << 0)
 
 /* Power Management */
 #define DOVE_PMU_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE | 0xd0000)
+#define DOVE_PMU_SIG_CTRL      (DOVE_PMU_VIRT_BASE + 0x802c)
 
 /* Real Time Clock */
 #define DOVE_RTC_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE | 0xd8500)
index 0ee70ff39e1105dfb096fbfe1551fdfb18b6663f..340bb7af529d13f3d7461edfa4b2975a67f3e7f6 100644 (file)
 #include <plat/gpio.h>
 #include <asm-generic/gpio.h>          /* cansleep wrappers */
 
-#define GPIO_MAX       64
+#define GPIO_MAX       72
 
 #define GPIO_BASE_LO           (DOVE_GPIO_VIRT_BASE + 0x00)
 #define GPIO_BASE_HI           (DOVE_GPIO_VIRT_BASE + 0x20)
 
-#define GPIO_BASE(pin)         ((pin < 32) ? GPIO_BASE_LO : GPIO_BASE_HI)
+#define GPIO_BASE(pin)         ((pin < 32) ? GPIO_BASE_LO :            \
+                                ((pin < 64) ? GPIO_BASE_HI :           \
+                                 DOVE_GPIO2_VIRT_BASE))
 
 #define GPIO_OUT(pin)          (GPIO_BASE(pin) + 0x00)
 #define GPIO_IO_CONF(pin)      (GPIO_BASE(pin) + 0x04)
diff --git a/arch/arm/mach-dove/mpp.c b/arch/arm/mach-dove/mpp.c
new file mode 100644 (file)
index 0000000..71db2bd
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * arch/arm/mach-dove/mpp.c
+ *
+ * MPP functions for Marvell Dove SoCs
+ *
+ * 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/gpio.h>
+#include <linux/io.h>
+
+#include <mach/dove.h>
+
+#include "mpp.h"
+
+#define MPP_NR_REGS 4
+#define MPP_CTRL(i)    ((i) == 3 ?                             \
+                        DOVE_MPP_CTRL4_VIRT_BASE :             \
+                        DOVE_MPP_VIRT_BASE + (i) * 4)
+#define PMU_SIG_REGS 2
+#define PMU_SIG_CTRL(i)        (DOVE_PMU_SIG_CTRL + (i) * 4)
+
+struct dove_mpp_grp {
+       int start;
+       int end;
+};
+
+static struct dove_mpp_grp dove_mpp_grp[] = {
+       [MPP_24_39] = {
+               .start  = 24,
+               .end    = 39,
+       },
+       [MPP_40_45] = {
+               .start  = 40,
+               .end    = 45,
+       },
+       [MPP_46_51] = {
+               .start  = 40,
+               .end    = 45,
+       },
+       [MPP_58_61] = {
+               .start  = 58,
+               .end    = 61,
+       },
+       [MPP_62_63] = {
+               .start  = 62,
+               .end    = 63,
+       },
+};
+
+static void dove_mpp_gpio_mode(int start, int end, int gpio_mode)
+{
+       int i;
+
+       for (i = start; i <= end; i++)
+               orion_gpio_set_valid(i, gpio_mode);
+}
+
+static void dove_mpp_dump_regs(void)
+{
+#ifdef DEBUG
+       int i;
+
+       pr_debug("MPP_CTRL regs:");
+       for (i = 0; i < MPP_NR_REGS; i++)
+               printk(" %08x", readl(MPP_CTRL(i)));
+       printk("\n");
+
+       pr_debug("PMU_SIG_CTRL regs:");
+       for (i = 0; i < PMU_SIG_REGS; i++)
+               printk(" %08x", readl(PMU_SIG_CTRL(i)));
+       printk("\n");
+
+       pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n", readl(DOVE_PMU_MPP_GENERAL_CTRL));
+       pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE));
+#endif
+}
+
+static void dove_mpp_cfg_nfc(int sel)
+{
+       u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+       mpp_gen_cfg &= ~0x1;
+       mpp_gen_cfg |= sel;
+       writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE);
+
+       dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
+}
+
+static void dove_mpp_cfg_au1(int sel)
+{
+       u32 mpp_ctrl4           = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+       u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1);
+       u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+       u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+       mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL);
+       ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1);
+       mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN);
+       global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO);
+
+       if (!sel || sel == 0x2)
+               dove_mpp_gpio_mode(52, 57, 0);
+       else
+               dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
+
+       if (sel & 0x1) {
+               global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
+               dove_mpp_gpio_mode(56, 57, 0);
+       }
+       if (sel & 0x2) {
+               mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN;
+               dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
+       }
+       if (sel & 0x4) {
+               ssp_ctrl1 |= DOVE_SSP_ON_AU1;
+               dove_mpp_gpio_mode(52, 55, 0);
+       }
+       if (sel & 0x8)
+               mpp_ctrl4 |= DOVE_AU1_GPIO_SEL;
+
+       writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
+       writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1);
+       writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE);
+       writel(global_cfg_2, DOVE_GLOBAL_CONFIG_2);
+}
+
+static void dove_mpp_conf_grp(int num, int sel, u32 *mpp_ctrl)
+{
+       int start = dove_mpp_grp[num].start;
+       int end = dove_mpp_grp[num].end;
+       int gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0;
+
+       *mpp_ctrl &= ~(0x1 << num);
+       *mpp_ctrl |= sel << num;
+
+       dove_mpp_gpio_mode(start, end, gpio_mode);
+}
+
+void __init dove_mpp_conf(unsigned int *mpp_list)
+{
+       u32 mpp_ctrl[MPP_NR_REGS];
+       u32 pmu_mpp_ctrl = 0;
+       u32 pmu_sig_ctrl[PMU_SIG_REGS];
+       int i;
+
+       /* Initialize gpiolib. */
+       orion_gpio_init();
+
+       for (i = 0; i < MPP_NR_REGS; i++)
+               mpp_ctrl[i] = readl(MPP_CTRL(i));
+
+       for (i = 0; i < PMU_SIG_REGS; i++)
+               pmu_sig_ctrl[i] = readl(PMU_SIG_CTRL(i));
+
+       pmu_mpp_ctrl = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+       dove_mpp_dump_regs();
+
+       for ( ; *mpp_list != MPP_END; mpp_list++) {
+               unsigned int num = MPP_NUM(*mpp_list);
+               unsigned int sel = MPP_SEL(*mpp_list);
+               int shift, gpio_mode;
+
+               if (num > MPP_MAX) {
+                       pr_err("dove: invalid MPP number (%u)\n", num);
+                       continue;
+               }
+
+               if (*mpp_list & MPP_NFC_MASK) {
+                       dove_mpp_cfg_nfc(sel);
+                       continue;
+               }
+
+               if (*mpp_list & MPP_AU1_MASK) {
+                       dove_mpp_cfg_au1(sel);
+                       continue;
+               }
+
+               if (*mpp_list & MPP_GRP_MASK) {
+                       dove_mpp_conf_grp(num, sel, &mpp_ctrl[3]);
+                       continue;
+               }
+
+               shift = (num & 7) << 2;
+               if (*mpp_list & MPP_PMU_MASK) {
+                       pmu_mpp_ctrl |= (0x1 << num);
+                       pmu_sig_ctrl[num / 8] &= ~(0xf << shift);
+                       pmu_sig_ctrl[num / 8] |= 0xf << shift;
+                       gpio_mode = 0;
+               } else {
+                       mpp_ctrl[num / 8] &= ~(0xf << shift);
+                       mpp_ctrl[num / 8] |= sel << shift;
+                       gpio_mode = GPIO_OUTPUT_OK | GPIO_INPUT_OK;
+               }
+
+               orion_gpio_set_valid(num, gpio_mode);
+       }
+
+       for (i = 0; i < MPP_NR_REGS; i++)
+               writel(mpp_ctrl[i], MPP_CTRL(i));
+
+       for (i = 0; i < PMU_SIG_REGS; i++)
+               writel(pmu_sig_ctrl[i], PMU_SIG_CTRL(i));
+
+       writel(pmu_mpp_ctrl, DOVE_PMU_MPP_GENERAL_CTRL);
+
+       dove_mpp_dump_regs();
+}
diff --git a/arch/arm/mach-dove/mpp.h b/arch/arm/mach-dove/mpp.h
new file mode 100644 (file)
index 0000000..2a43ce4
--- /dev/null
@@ -0,0 +1,220 @@
+#ifndef __ARCH_DOVE_MPP_CODED_H
+#define __ARCH_DOVE_MPP_CODED_H
+
+#define MPP(_num, _mode, _pmu, _grp, _au1, _nfc) (     \
+/* MPP/group number */         ((_num) & 0xff) |               \
+/* MPP select value */         (((_mode) & 0xf) << 8) |        \
+/* MPP PMU */                  ((!!(_pmu)) << 12) |            \
+/* group flag */               ((!!(_grp)) << 13) |            \
+/* AU1 flag */                 ((!!(_au1)) << 14) |            \
+/* NFCE flag */                        ((!!(_nfc)) << 15))
+
+#define MPP_MAX        71
+
+#define MPP_NUM(x)    ((x) & 0xff)
+#define MPP_SEL(x)    (((x) >> 8) & 0xf)
+
+#define MPP_PMU_MASK           MPP(0, 0x0, 1, 0, 0, 0)
+#define MPP_GRP_MASK           MPP(0, 0x0, 0, 1, 0, 0)
+#define MPP_AU1_MASK           MPP(0, 0x0, 0, 0, 1, 0)
+#define MPP_NFC_MASK           MPP(0, 0x0, 0, 0, 0, 1)
+
+#define MPP_END                        MPP(0xff, 0xf, 1, 1, 1, 1)
+
+#define MPP_PMU_DRIVE_0                0x1
+#define MPP_PMU_DRIVE_1                0x2
+#define MPP_PMU_SDI            0x3
+#define MPP_PMU_CPU_PWRDWN     0x4
+#define MPP_PMU_STBY_PWRDWN    0x5
+#define MPP_PMU_CORE_PWR_GOOD  0x8
+#define MPP_PMU_BAT_FAULT      0xa
+#define MPP_PMU_EXT0_WU                0xb
+#define MPP_PMU_EXT1_WU                0xc
+#define MPP_PMU_EXT2_WU                0xd
+#define MPP_PMU_BLINK          0xe
+#define MPP_PMU(_num, _mode)   MPP((_num), MPP_PMU_##_mode, 1, 0, 0, 0)
+
+#define MPP_PIN(_num, _mode)   MPP((_num), (_mode), 0, 0, 0, 0)
+#define MPP_GRP(_grp, _mode)   MPP((_grp), (_mode), 0, 1, 0, 0)
+#define MPP_GRP_AU1(_mode)     MPP(0, (_mode), 0, 0, 1, 0)
+#define MPP_GRP_NFC(_mode)     MPP(0, (_mode), 0, 0, 0, 1)
+
+#define MPP0_GPIO0             MPP_PIN(0, 0x0)
+#define MPP0_UA2_RTSn          MPP_PIN(0, 0x2)
+#define MPP0_SDIO0_CD          MPP_PIN(0, 0x3)
+#define MPP0_LCD0_PWM          MPP_PIN(0, 0xf)
+
+#define MPP1_GPIO1             MPP_PIN(1, 0x0)
+#define MPP1_UA2_CTSn          MPP_PIN(1, 0x2)
+#define MPP1_SDIO0_WP          MPP_PIN(1, 0x3)
+#define MPP1_LCD1_PWM          MPP_PIN(1, 0xf)
+
+#define MPP2_GPIO2             MPP_PIN(2, 0x0)
+#define MPP2_SATA_PRESENT      MPP_PIN(2, 0x1)
+#define MPP2_UA2_TXD           MPP_PIN(2, 0x2)
+#define MPP2_SDIO0_BUS_POWER   MPP_PIN(2, 0x3)
+#define MPP2_UA_RTSn1          MPP_PIN(2, 0x4)
+
+#define MPP3_GPIO3             MPP_PIN(3, 0x0)
+#define MPP3_SATA_ACT          MPP_PIN(3, 0x1)
+#define MPP3_UA2_RXD           MPP_PIN(3, 0x2)
+#define MPP3_SDIO0_LED_CTRL    MPP_PIN(3, 0x3)
+#define MPP3_UA_CTSn1          MPP_PIN(3, 0x4)
+#define MPP3_SPI_LCD_CS1       MPP_PIN(3, 0xf)
+
+#define MPP4_GPIO4             MPP_PIN(4, 0x0)
+#define MPP4_UA3_RTSn          MPP_PIN(4, 0x2)
+#define MPP4_SDIO1_CD          MPP_PIN(4, 0x3)
+#define MPP4_SPI_1_MISO                MPP_PIN(4, 0x4)
+
+#define MPP5_GPIO5             MPP_PIN(5, 0x0)
+#define MPP5_UA3_CTSn          MPP_PIN(5, 0x2)
+#define MPP5_SDIO1_WP          MPP_PIN(5, 0x3)
+#define MPP5_SPI_1_CS          MPP_PIN(5, 0x4)
+
+#define MPP6_GPIO6             MPP_PIN(6, 0x0)
+#define MPP6_UA3_TXD           MPP_PIN(6, 0x2)
+#define MPP6_SDIO1_BUS_POWER   MPP_PIN(6, 0x3)
+#define MPP6_SPI_1_MOSI                MPP_PIN(6, 0x4)
+
+#define MPP7_GPIO7             MPP_PIN(7, 0x0)
+#define MPP7_UA3_RXD           MPP_PIN(7, 0x2)
+#define MPP7_SDIO1_LED_CTRL    MPP_PIN(7, 0x3)
+#define MPP7_SPI_1_SCK         MPP_PIN(7, 0x4)
+
+#define MPP8_GPIO8             MPP_PIN(8, 0x0)
+#define MPP8_WD_RST_OUT                MPP_PIN(8, 0x1)
+
+#define MPP9_GPIO9             MPP_PIN(9, 0x0)
+#define MPP9_PEX1_CLKREQn      MPP_PIN(9, 0x5)
+
+#define MPP10_GPIO10           MPP_PIN(10, 0x0)
+#define MPP10_SSP_SCLK         MPP_PIN(10, 0x5)
+
+#define MPP11_GPIO11           MPP_PIN(11, 0x0)
+#define MPP11_SATA_PRESENT     MPP_PIN(11, 0x1)
+#define MPP11_SATA_ACT         MPP_PIN(11, 0x2)
+#define MPP11_SDIO0_LED_CTRL   MPP_PIN(11, 0x3)
+#define MPP11_SDIO1_LED_CTRL   MPP_PIN(11, 0x4)
+#define MPP11_PEX0_CLKREQn     MPP_PIN(11, 0x5)
+
+#define MPP12_GPIO12           MPP_PIN(12, 0x0)
+#define MPP12_SATA_ACT         MPP_PIN(12, 0x1)
+#define MPP12_UA2_RTSn         MPP_PIN(12, 0x2)
+#define MPP12_AD0_I2S_EXT_MCLK MPP_PIN(12, 0x3)
+#define MPP12_SDIO1_CD         MPP_PIN(12, 0x4)
+
+#define MPP13_GPIO13           MPP_PIN(13, 0x0)
+#define MPP13_UA2_CTSn         MPP_PIN(13, 0x2)
+#define MPP13_AD1_I2S_EXT_MCLK MPP_PIN(13, 0x3)
+#define MPP13_SDIO1WP          MPP_PIN(13, 0x4)
+#define MPP13_SSP_EXTCLK       MPP_PIN(13, 0x5)
+
+#define MPP14_GPIO14           MPP_PIN(14, 0x0)
+#define MPP14_UA2_TXD          MPP_PIN(14, 0x2)
+#define MPP14_SDIO1_BUS_POWER  MPP_PIN(14, 0x4)
+#define MPP14_SSP_RXD          MPP_PIN(14, 0x5)
+
+#define MPP15_GPIO15           MPP_PIN(15, 0x0)
+#define MPP15_UA2_RXD          MPP_PIN(15, 0x2)
+#define MPP15_SDIO1_LED_CTRL   MPP_PIN(15, 0x4)
+#define MPP15_SSP_SFRM         MPP_PIN(15, 0x5)
+
+#define MPP16_GPIO16           MPP_PIN(16, 0x0)
+#define MPP16_UA3_RTSn         MPP_PIN(16, 0x2)
+#define MPP16_SDIO0_CD         MPP_PIN(16, 0x3)
+#define MPP16_SPI_LCD_CS1      MPP_PIN(16, 0x4)
+#define MPP16_AC97_SDATA_IN1   MPP_PIN(16, 0x5)
+
+#define MPP17_GPIO17           MPP_PIN(17, 0x0)
+#define MPP17_AC97_SYSCLK_OUT  MPP_PIN(17, 0x1)
+#define MPP17_UA3_CTSn         MPP_PIN(17, 0x2)
+#define MPP17_SDIO0_WP         MPP_PIN(17, 0x3)
+#define MPP17_TW_SDA2          MPP_PIN(17, 0x4)
+#define MPP17_AC97_SDATA_IN2   MPP_PIN(17, 0x5)
+
+#define MPP18_GPIO18           MPP_PIN(18, 0x0)
+#define MPP18_UA3_TXD          MPP_PIN(18, 0x2)
+#define MPP18_SDIO0_BUS_POWER  MPP_PIN(18, 0x3)
+#define MPP18_LCD0_PWM         MPP_PIN(18, 0x4)
+#define MPP18_AC_SDATA_IN3     MPP_PIN(18, 0x5)
+
+#define MPP19_GPIO19           MPP_PIN(19, 0x0)
+#define MPP19_UA3_RXD          MPP_PIN(19, 0x2)
+#define MPP19_SDIO0_LED_CTRL   MPP_PIN(19, 0x3)
+#define MPP19_TW_SCK2          MPP_PIN(19, 0x4)
+
+#define MPP20_GPIO20           MPP_PIN(20, 0x0)
+#define MPP20_AC97_SYSCLK_OUT  MPP_PIN(20, 0x1)
+#define MPP20_SPI_LCD_MISO     MPP_PIN(20, 0x2)
+#define MPP20_SDIO1_CD         MPP_PIN(20, 0x3)
+#define MPP20_SDIO0_CD         MPP_PIN(20, 0x5)
+#define MPP20_SPI_1_MISO       MPP_PIN(20, 0x6)
+
+#define MPP21_GPIO21           MPP_PIN(21, 0x0)
+#define MPP21_UA1_RTSn         MPP_PIN(21, 0x1)
+#define MPP21_SPI_LCD_CS0      MPP_PIN(21, 0x2)
+#define MPP21_SDIO1_WP         MPP_PIN(21, 0x3)
+#define MPP21_SSP_SFRM         MPP_PIN(21, 0x4)
+#define MPP21_SDIO0_WP         MPP_PIN(21, 0x5)
+#define MPP21_SPI_1_CS         MPP_PIN(21, 0x6)
+
+#define MPP22_GPIO22           MPP_PIN(22, 0x0)
+#define MPP22_UA1_CTSn         MPP_PIN(22, 0x1)
+#define MPP22_SPI_LCD_MOSI     MPP_PIN(22, 0x2)
+#define MPP22_SDIO1_BUS_POWER  MPP_PIN(22, 0x3)
+#define MPP22_SSP_TXD          MPP_PIN(22, 0x4)
+#define MPP22_SDIO0_BUS_POWER  MPP_PIN(22, 0x5)
+#define MPP22_SPI_1_MOSI       MPP_PIN(22, 0x6)
+
+#define MPP23_GPIO23           MPP_PIN(23, 0x0)
+#define MPP23_SPI_LCD_SCK      MPP_PIN(23, 0x2)
+#define MPP23_SDIO1_LED_CTRL   MPP_PIN(23, 0x3)
+#define MPP23_SSP_SCLK         MPP_PIN(23, 0x4)
+#define MPP23_SDIO0_LED_CTRL   MPP_PIN(23, 0x5)
+#define MPP23_SPI_1_SCK                MPP_PIN(23, 0x6)
+
+/* for MPP groups _num is a group index */
+enum dove_mpp_grp_idx {
+       MPP_24_39 = 2,
+       MPP_40_45 = 0,
+       MPP_46_51 = 1,
+       MPP_58_61 = 5,
+       MPP_62_63 = 4,
+};
+
+#define MPP24_39_GPIO          MPP_GRP(MPP_24_39, 0x1)
+#define MPP24_39_CAM           MPP_GRP(MPP_24_39, 0x0)
+
+#define MPP40_45_GPIO          MPP_GRP(MPP_40_45, 0x1)
+#define MPP40_45_SD0           MPP_GRP(MPP_40_45, 0x0)
+
+#define MPP46_51_GPIO          MPP_GRP(MPP_46_51, 0x1)
+#define MPP46_51_SD1           MPP_GRP(MPP_46_51, 0x0)
+
+#define MPP58_61_GPIO          MPP_GRP(MPP_58_61, 0x1)
+#define MPP58_61_SPI           MPP_GRP(MPP_58_61, 0x0)
+
+#define MPP62_63_GPIO          MPP_GRP(MPP_62_63, 0x1)
+#define MPP62_63_UA1           MPP_GRP(MPP_62_63, 0x0)
+
+/* The MPP[64:71] control differs from other groups */
+#define MPP64_71_GPO           MPP_GRP_NFC(0x1)
+#define MPP64_71_NFC           MPP_GRP_NFC(0x0)
+
+/*
+ * The MPP[52:57] functionality is encoded by 4 bits in different
+ * registers. The _num field in this case encodes those bits in
+ * correspodence with Table 135 of 88AP510 Functional specification
+ */
+#define MPP52_57_AU1           MPP_GRP_AU1(0x0)
+#define MPP52_57_AU1_GPIO57    MPP_GRP_AU1(0x2)
+#define MPP52_57_GPIO          MPP_GRP_AU1(0xa)
+#define MPP52_57_TW_GPIO       MPP_GRP_AU1(0xb)
+#define MPP52_57_AU1_SSP       MPP_GRP_AU1(0xc)
+#define MPP52_57_SSP_GPIO      MPP_GRP_AU1(0xe)
+#define MPP52_57_SSP_TW                MPP_GRP_AU1(0xf)
+
+void dove_mpp_conf(unsigned int *mpp_list);
+
+#endif /* __ARCH_DOVE_MPP_CODED_H */
index 34106335c728f31527dc59dbc05d5978165ae365..7fc603b468916014d12499c26825e945655a1941 100644 (file)
@@ -45,18 +45,18 @@ config MACH_GURUPLUG
          Marvell GuruPlug Reference Board.
 
 config MACH_TS219
-       bool "QNAP TS-110, TS-119, TS-210, TS-219 and TS-219P Turbo NAS"
+       bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
        help
          Say 'Y' here if you want your kernel to support the
-         QNAP TS-110, TS-119, TS-210, TS-219 and TS-219P Turbo NAS
-         devices.
+         QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and
+         TS-219P+ Turbo NAS devices.
 
 config MACH_TS41X
-       bool "QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS"
+       bool "QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo NAS"
        help
          Say 'Y' here if you want your kernel to support the
-         QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS
-         devices.
+         QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo
+         NAS devices.
 
 config MACH_DOCKSTAR
        bool "Seagate FreeAgent DockStar"
index 6710bd7773b8b0b1e603a52914dbbce5f4cd34bc..dc999c4c5806f107d3d5effaab49187eb3b471ec 100644 (file)
@@ -80,15 +80,19 @@ static unsigned int qnap_ts219_mpp_config[] __initdata = {
        MPP11_UART0_RXD,
        MPP13_UART1_TXD,        /* PIC controller */
        MPP14_UART1_RXD,        /* PIC controller */
-       MPP15_GPIO,             /* USB Copy button */
-       MPP16_GPIO,             /* Reset button */
+       MPP15_GPIO,             /* USB Copy button (on devices with 88F6281) */
+       MPP16_GPIO,             /* Reset button (on devices with 88F6281) */
        MPP36_GPIO,             /* RAM: 0: 256 MB, 1: 512 MB */
+       MPP37_GPIO,             /* Reset button (on devices with 88F6282) */
+       MPP43_GPIO,             /* USB Copy button (on devices with 88F6282) */
        MPP44_GPIO,             /* Board ID: 0: TS-11x, 1: TS-21x */
        0
 };
 
 static void __init qnap_ts219_init(void)
 {
+       u32 dev, rev;
+
        /*
         * Basic setup. Needs to be called early.
         */
@@ -100,6 +104,14 @@ static void __init qnap_ts219_init(void)
        qnap_tsx1x_register_flash();
        kirkwood_i2c_init();
        i2c_register_board_info(0, &qnap_ts219_i2c_rtc, 1);
+
+       kirkwood_pcie_id(&dev, &rev);
+       if (dev == MV88F6282_DEV_ID) {
+               qnap_ts219_buttons[0].gpio = 43; /* USB Copy button */
+               qnap_ts219_buttons[1].gpio = 37; /* Reset button */
+               qnap_ts219_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
+       }
+
        kirkwood_ge00_init(&qnap_ts219_ge00_data);
        kirkwood_sata_init(&qnap_ts219_sata_data);
        kirkwood_ehci_init();
index 3587a281d993825076e9e16032ad4c8b76ec4b88..9a44029915e2a4fd7fbab3fa8580b7611cbf69ed 100644 (file)
@@ -119,6 +119,8 @@ static unsigned int qnap_ts41x_mpp_config[] __initdata = {
 
 static void __init qnap_ts41x_init(void)
 {
+       u32 dev, rev;
+
        /*
         * Basic setup. Needs to be called early.
         */
@@ -130,8 +132,15 @@ static void __init qnap_ts41x_init(void)
        qnap_tsx1x_register_flash();
        kirkwood_i2c_init();
        i2c_register_board_info(0, &qnap_ts41x_i2c_rtc, 1);
+
+       kirkwood_pcie_id(&dev, &rev);
+       if (dev == MV88F6282_DEV_ID) {
+               qnap_ts41x_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
+               qnap_ts41x_ge01_data.phy_addr = MV643XX_ETH_PHY_ADDR(1);
+       }
        kirkwood_ge00_init(&qnap_ts41x_ge00_data);
        kirkwood_ge01_init(&qnap_ts41x_ge01_data);
+
        kirkwood_sata_init(&qnap_ts41x_sata_data);
        kirkwood_ehci_init();
        platform_device_register(&qnap_ts41x_button_device);
index 0711d3b620ad2286ea5aaabd035fbc1e19627e81..67793a6902727eeb67fb53b5d688e2a738efc185 100644 (file)
@@ -37,25 +37,38 @@ config MACH_TTC_DKB
          Say 'Y' here if you want to support the Marvell PXA910-based
          TTC_DKB Development Board.
 
+config MACH_BROWNSTONE
+       bool "Marvell's Brownstone Development Platform"
+       depends on !CPU_MOHAWK
+       select CPU_MMP2
+       help
+         Say 'Y' here if you want to support the Marvell MMP2-based
+         Brown Development Platform.
+         MMP2-based board can't be co-existed with PXA168-based &
+         PXA910-based development board. Since MMP2 is compatible to
+         ARMv7 architecture.
+
 config MACH_FLINT
        bool "Marvell's Flint Development Platform"
+       depends on !CPU_MOHAWK
        select CPU_MMP2
        help
          Say 'Y' here if you want to support the Marvell MMP2-based
          Flint Development Platform.
          MMP2-based board can't be co-existed with PXA168-based &
          PXA910-based development board. Since MMP2 is compatible to
-         ARMv6 architecture.
+         ARMv7 architecture.
 
 config MACH_MARVELL_JASPER
        bool "Marvell's Jasper Development Platform"
+       depends on !CPU_MOHAWK
        select CPU_MMP2
        help
          Say 'Y' here if you want to support the Marvell MMP2-base
          Jasper Development Platform.
          MMP2-based board can't be co-existed with PXA168-based &
          PXA910-based development board. Since MMP2 is compatible to
-         ARMv6 architecture.
+         ARMv7 architecture.
 
 config MACH_TETON_BGA
        bool "Marvell's PXA168 Teton BGA Development Board"
@@ -80,8 +93,7 @@ config CPU_PXA910
 
 config CPU_MMP2
        bool
-       select CPU_V6
-       select CPU_32v6K
+       select CPU_PJ4
        help
-         Select code specific to MMP2. MMP2 is ARMv6 compatible.
+         Select code specific to MMP2. MMP2 is ARMv7 compatible.
 endif
index 751cdbf733c852c5970e77e32013d28931b0113e..5c68382141af09d902ae911694a08117861bc0cd 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_MACH_ZYLONITE2)  += aspenite.o
 obj-$(CONFIG_MACH_AVENGERS_LITE)+= avengers_lite.o
 obj-$(CONFIG_MACH_TAVOREVB)    += tavorevb.o
 obj-$(CONFIG_MACH_TTC_DKB)     += ttc_dkb.o
+obj-$(CONFIG_MACH_BROWNSTONE)  += brownstone.o
 obj-$(CONFIG_MACH_FLINT)       += flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_TETON_BGA)   += teton_bga.o
diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
new file mode 100644 (file)
index 0000000..7bb78fd
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *  linux/arch/arm/mach-mmp/brownstone.c
+ *
+ *  Support for the Marvell Brownstone Development Platform.
+ *
+ *  Copyright (C) 2009-2010 Marvell International 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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/max8649.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max8925.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-mmp2.h>
+#include <mach/mmp2.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+#define BROWNSTONE_NR_IRQS     (IRQ_BOARD_START + 40)
+
+#define GPIO_5V_ENABLE         (89)
+
+static unsigned long brownstone_pin_config[] __initdata = {
+       /* UART1 */
+       GPIO29_UART1_RXD,
+       GPIO30_UART1_TXD,
+
+       /* UART3 */
+       GPIO51_UART3_RXD,
+       GPIO52_UART3_TXD,
+
+       /* DFI */
+       GPIO168_DFI_D0,
+       GPIO167_DFI_D1,
+       GPIO166_DFI_D2,
+       GPIO165_DFI_D3,
+       GPIO107_DFI_D4,
+       GPIO106_DFI_D5,
+       GPIO105_DFI_D6,
+       GPIO104_DFI_D7,
+       GPIO111_DFI_D8,
+       GPIO164_DFI_D9,
+       GPIO163_DFI_D10,
+       GPIO162_DFI_D11,
+       GPIO161_DFI_D12,
+       GPIO110_DFI_D13,
+       GPIO109_DFI_D14,
+       GPIO108_DFI_D15,
+       GPIO143_ND_nCS0,
+       GPIO144_ND_nCS1,
+       GPIO147_ND_nWE,
+       GPIO148_ND_nRE,
+       GPIO150_ND_ALE,
+       GPIO149_ND_CLE,
+       GPIO112_ND_RDY0,
+       GPIO160_ND_RDY1,
+
+       /* PMIC */
+       PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
+
+       /* MMC0 */
+       GPIO131_MMC1_DAT3 | MFP_PULL_HIGH,
+       GPIO132_MMC1_DAT2 | MFP_PULL_HIGH,
+       GPIO133_MMC1_DAT1 | MFP_PULL_HIGH,
+       GPIO134_MMC1_DAT0 | MFP_PULL_HIGH,
+       GPIO136_MMC1_CMD | MFP_PULL_HIGH,
+       GPIO139_MMC1_CLK,
+       GPIO140_MMC1_CD | MFP_PULL_LOW,
+       GPIO141_MMC1_WP | MFP_PULL_LOW,
+
+       /* MMC1 */
+       GPIO37_MMC2_DAT3 | MFP_PULL_HIGH,
+       GPIO38_MMC2_DAT2 | MFP_PULL_HIGH,
+       GPIO39_MMC2_DAT1 | MFP_PULL_HIGH,
+       GPIO40_MMC2_DAT0 | MFP_PULL_HIGH,
+       GPIO41_MMC2_CMD | MFP_PULL_HIGH,
+       GPIO42_MMC2_CLK,
+
+       /* MMC2 */
+       GPIO165_MMC3_DAT7 | MFP_PULL_HIGH,
+       GPIO162_MMC3_DAT6 | MFP_PULL_HIGH,
+       GPIO166_MMC3_DAT5 | MFP_PULL_HIGH,
+       GPIO163_MMC3_DAT4 | MFP_PULL_HIGH,
+       GPIO167_MMC3_DAT3 | MFP_PULL_HIGH,
+       GPIO164_MMC3_DAT2 | MFP_PULL_HIGH,
+       GPIO168_MMC3_DAT1 | MFP_PULL_HIGH,
+       GPIO111_MMC3_DAT0 | MFP_PULL_HIGH,
+       GPIO112_MMC3_CMD | MFP_PULL_HIGH,
+       GPIO151_MMC3_CLK,
+
+       /* 5V regulator */
+       GPIO89_GPIO,
+};
+
+static struct regulator_consumer_supply max8649_supply[] = {
+       REGULATOR_SUPPLY("vcc_core", NULL),
+};
+
+static struct regulator_init_data max8649_init_data = {
+       .constraints    = {
+               .name           = "vcc_core range",
+               .min_uV         = 1150000,
+               .max_uV         = 1280000,
+               .always_on      = 1,
+               .boot_on        = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &max8649_supply[0],
+};
+
+static struct max8649_platform_data brownstone_max8649_info = {
+       .mode           = 2,    /* VID1 = 1, VID0 = 0 */
+       .extclk         = 0,
+       .ramp_timing    = MAX8649_RAMP_32MV,
+       .regulator      = &max8649_init_data,
+};
+
+static struct regulator_consumer_supply brownstone_v_5vp_supplies[] = {
+       REGULATOR_SUPPLY("v_5vp", NULL),
+};
+
+static struct regulator_init_data brownstone_v_5vp_data = {
+       .constraints    = {
+               .valid_ops_mask         = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(brownstone_v_5vp_supplies),
+       .consumer_supplies      = brownstone_v_5vp_supplies,
+};
+
+static struct fixed_voltage_config brownstone_v_5vp = {
+       .supply_name            = "v_5vp",
+       .microvolts             = 5000000,
+       .gpio                   = GPIO_5V_ENABLE,
+       .enable_high            = 1,
+       .enabled_at_boot        = 1,
+       .init_data              = &brownstone_v_5vp_data,
+};
+
+static struct platform_device brownstone_v_5vp_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = 1,
+       .dev = {
+               .platform_data = &brownstone_v_5vp,
+       },
+};
+
+static struct max8925_platform_data brownstone_max8925_info = {
+       .irq_base               = IRQ_BOARD_START,
+};
+
+static struct i2c_board_info brownstone_twsi1_info[] = {
+       [0] = {
+               .type           = "max8649",
+               .addr           = 0x60,
+               .platform_data  = &brownstone_max8649_info,
+       },
+       [1] = {
+               .type           = "max8925",
+               .addr           = 0x3c,
+               .irq            = IRQ_MMP2_PMIC,
+               .platform_data  = &brownstone_max8925_info,
+       },
+};
+
+static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
+       .max_speed      = 25000000,
+};
+
+static void __init brownstone_init(void)
+{
+       mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
+
+       /* on-chip devices */
+       mmp2_add_uart(1);
+       mmp2_add_uart(3);
+       mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
+       mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
+
+       /* enable 5v regulator */
+       platform_device_register(&brownstone_v_5vp_device);
+}
+
+MACHINE_START(BROWNSTONE, "Brownstone Development Platform")
+       /* Maintainer: Haojian Zhuang <haojian.zhuang@marvell.com> */
+       .map_io         = mmp_map_io,
+       .nr_irqs        = BROWNSTONE_NR_IRQS,
+       .init_irq       = mmp2_init_irq,
+       .timer          = &mmp2_timer,
+       .init_machine   = brownstone_init,
+MACHINE_END
index bdeb6db4d49a1a143396abcaec6b7fe3552a2946..c4fd806b15b42ad282533587e54a8378eb514c3d 100644 (file)
@@ -47,7 +47,7 @@ static unsigned long flint_pin_config[] __initdata = {
        GPIO113_SMC_RDY,
 
        /*Ethernet*/
-       GPIO155_GPIO155,
+       GPIO155_GPIO,
 
        /* DFI */
        GPIO168_DFI_D0,
index 761c2dacc07903ed604e7ad8301d8eb54d6fd2b0..117e30366087fdc486b4a73241a3bb5b6527ab84 100644 (file)
 #define MFP_DRIVE_FAST         (0x8 << 13)
 
 /* GPIO */
-#define GPIO0_GPIO0            MFP_CFG(GPIO0, AF0)
-#define GPIO1_GPIO1            MFP_CFG(GPIO1, AF0)
-#define GPIO2_GPIO2            MFP_CFG(GPIO2, AF0)
-#define GPIO3_GPIO3            MFP_CFG(GPIO3, AF0)
-#define GPIO4_GPIO4            MFP_CFG(GPIO4, AF0)
-#define GPIO5_GPIO5            MFP_CFG(GPIO5, AF0)
-#define GPIO6_GPIO6            MFP_CFG(GPIO6, AF0)
-#define GPIO7_GPIO7            MFP_CFG(GPIO7, AF0)
-#define GPIO8_GPIO8            MFP_CFG(GPIO8, AF0)
-#define GPIO9_GPIO9            MFP_CFG(GPIO9, AF0)
-#define GPIO10_GPIO10          MFP_CFG(GPIO10, AF0)
-#define GPIO11_GPIO11          MFP_CFG(GPIO11, AF0)
-#define GPIO12_GPIO12          MFP_CFG(GPIO12, AF0)
-#define GPIO13_GPIO13          MFP_CFG(GPIO13, AF0)
-#define GPIO14_GPIO14          MFP_CFG(GPIO14, AF0)
-#define GPIO15_GPIO15          MFP_CFG(GPIO15, AF0)
-#define GPIO16_GPIO16          MFP_CFG(GPIO16, AF0)
-#define GPIO17_GPIO17          MFP_CFG(GPIO17, AF0)
-#define GPIO18_GPIO18          MFP_CFG(GPIO18, AF0)
-#define GPIO19_GPIO19          MFP_CFG(GPIO19, AF0)
-#define GPIO20_GPIO20          MFP_CFG(GPIO20, AF0)
-#define GPIO21_GPIO21          MFP_CFG(GPIO21, AF0)
-#define GPIO22_GPIO22          MFP_CFG(GPIO22, AF0)
-#define GPIO23_GPIO23          MFP_CFG(GPIO23, AF0)
-#define GPIO24_GPIO24          MFP_CFG(GPIO24, AF0)
-#define GPIO25_GPIO25          MFP_CFG(GPIO25, AF0)
-#define GPIO26_GPIO26          MFP_CFG(GPIO26, AF0)
-#define GPIO27_GPIO27          MFP_CFG(GPIO27, AF0)
-#define GPIO28_GPIO28          MFP_CFG(GPIO28, AF0)
-#define GPIO29_GPIO29          MFP_CFG(GPIO29, AF0)
-#define GPIO30_GPIO30          MFP_CFG(GPIO30, AF0)
-#define GPIO31_GPIO31          MFP_CFG(GPIO31, AF0)
-#define GPIO32_GPIO32          MFP_CFG(GPIO32, AF0)
-#define GPIO33_GPIO33          MFP_CFG(GPIO33, AF0)
-#define GPIO34_GPIO34          MFP_CFG(GPIO34, AF0)
-#define GPIO35_GPIO35          MFP_CFG(GPIO35, AF0)
-#define GPIO36_GPIO36          MFP_CFG(GPIO36, AF0)
-#define GPIO37_GPIO37          MFP_CFG(GPIO37, AF0)
-#define GPIO38_GPIO38          MFP_CFG(GPIO38, AF0)
-#define GPIO39_GPIO39          MFP_CFG(GPIO39, AF0)
-#define GPIO40_GPIO40          MFP_CFG(GPIO40, AF0)
-#define GPIO41_GPIO41          MFP_CFG(GPIO41, AF0)
-#define GPIO42_GPIO42          MFP_CFG(GPIO42, AF0)
-#define GPIO43_GPIO43          MFP_CFG(GPIO43, AF0)
-#define GPIO44_GPIO44          MFP_CFG(GPIO44, AF0)
-#define GPIO45_GPIO45          MFP_CFG(GPIO45, AF0)
-#define GPIO46_GPIO46          MFP_CFG(GPIO46, AF0)
-#define GPIO47_GPIO47          MFP_CFG(GPIO47, AF0)
-#define GPIO48_GPIO48          MFP_CFG(GPIO48, AF0)
-#define GPIO49_GPIO49          MFP_CFG(GPIO49, AF0)
-#define GPIO50_GPIO50          MFP_CFG(GPIO50, AF0)
-#define GPIO51_GPIO51          MFP_CFG(GPIO51, AF0)
-#define GPIO52_GPIO52          MFP_CFG(GPIO52, AF0)
-#define GPIO53_GPIO53          MFP_CFG(GPIO53, AF0)
-#define GPIO54_GPIO54          MFP_CFG(GPIO54, AF0)
-#define GPIO55_GPIO55          MFP_CFG(GPIO55, AF0)
-#define GPIO56_GPIO56          MFP_CFG(GPIO56, AF0)
-#define GPIO57_GPIO57          MFP_CFG(GPIO57, AF0)
-#define GPIO58_GPIO58          MFP_CFG(GPIO58, AF0)
-#define GPIO59_GPIO59          MFP_CFG(GPIO59, AF0)
-#define GPIO60_GPIO60          MFP_CFG(GPIO60, AF0)
-#define GPIO61_GPIO61          MFP_CFG(GPIO61, AF0)
-#define GPIO62_GPIO62          MFP_CFG(GPIO62, AF0)
-#define GPIO63_GPIO63          MFP_CFG(GPIO63, AF0)
-#define GPIO64_GPIO64          MFP_CFG(GPIO64, AF0)
-#define GPIO65_GPIO65          MFP_CFG(GPIO65, AF0)
-#define GPIO66_GPIO66          MFP_CFG(GPIO66, AF0)
-#define GPIO67_GPIO67          MFP_CFG(GPIO67, AF0)
-#define GPIO68_GPIO68          MFP_CFG(GPIO68, AF0)
-#define GPIO69_GPIO69          MFP_CFG(GPIO69, AF0)
-#define GPIO70_GPIO70          MFP_CFG(GPIO70, AF0)
-#define GPIO71_GPIO71          MFP_CFG(GPIO71, AF0)
-#define GPIO72_GPIO72          MFP_CFG(GPIO72, AF0)
-#define GPIO73_GPIO73          MFP_CFG(GPIO73, AF0)
-#define GPIO74_GPIO74          MFP_CFG(GPIO74, AF0)
-#define GPIO75_GPIO75          MFP_CFG(GPIO75, AF0)
-#define GPIO76_GPIO76          MFP_CFG(GPIO76, AF0)
-#define GPIO77_GPIO77          MFP_CFG(GPIO77, AF0)
-#define GPIO78_GPIO78          MFP_CFG(GPIO78, AF0)
-#define GPIO79_GPIO79          MFP_CFG(GPIO79, AF0)
-#define GPIO80_GPIO80          MFP_CFG(GPIO80, AF0)
-#define GPIO81_GPIO81          MFP_CFG(GPIO81, AF0)
-#define GPIO82_GPIO82          MFP_CFG(GPIO82, AF0)
-#define GPIO83_GPIO83          MFP_CFG(GPIO83, AF0)
-#define GPIO84_GPIO84          MFP_CFG(GPIO84, AF0)
-#define GPIO85_GPIO85          MFP_CFG(GPIO85, AF0)
-#define GPIO86_GPIO86          MFP_CFG(GPIO86, AF0)
-#define GPIO87_GPIO87          MFP_CFG(GPIO87, AF0)
-#define GPIO88_GPIO88          MFP_CFG(GPIO88, AF0)
-#define GPIO89_GPIO89          MFP_CFG(GPIO89, AF0)
-#define GPIO90_GPIO90          MFP_CFG(GPIO90, AF0)
-#define GPIO91_GPIO91          MFP_CFG(GPIO91, AF0)
-#define GPIO92_GPIO92          MFP_CFG(GPIO92, AF0)
-#define GPIO93_GPIO93          MFP_CFG(GPIO93, AF0)
-#define GPIO94_GPIO94          MFP_CFG(GPIO94, AF0)
-#define GPIO95_GPIO95          MFP_CFG(GPIO95, AF0)
-#define GPIO96_GPIO96          MFP_CFG(GPIO96, AF0)
-#define GPIO97_GPIO97          MFP_CFG(GPIO97, AF0)
-#define GPIO98_GPIO98          MFP_CFG(GPIO98, AF0)
-#define GPIO99_GPIO99          MFP_CFG(GPIO99, AF0)
-#define GPIO100_GPIO100                MFP_CFG(GPIO100, AF0)
-#define GPIO101_GPIO101                MFP_CFG(GPIO101, AF0)
-#define GPIO102_GPIO102                MFP_CFG(GPIO102, AF1)
-#define GPIO103_GPIO103                MFP_CFG(GPIO103, AF1)
-#define GPIO104_GPIO104                MFP_CFG(GPIO104, AF1)
-#define GPIO105_GPIO105                MFP_CFG(GPIO105, AF1)
-#define GPIO106_GPIO106                MFP_CFG(GPIO106, AF1)
-#define GPIO107_GPIO107                MFP_CFG(GPIO107, AF1)
-#define GPIO108_GPIO108                MFP_CFG(GPIO108, AF1)
-#define GPIO109_GPIO109                MFP_CFG(GPIO109, AF1)
-#define GPIO110_GPIO110                MFP_CFG(GPIO110, AF1)
-#define GPIO111_GPIO111                MFP_CFG(GPIO111, AF1)
-#define GPIO112_GPIO112                MFP_CFG(GPIO112, AF1)
-#define GPIO113_GPIO113                MFP_CFG(GPIO113, AF1)
-#define GPIO114_GPIO114                MFP_CFG(GPIO114, AF0)
-#define GPIO115_GPIO115                MFP_CFG(GPIO115, AF0)
-#define GPIO116_GPIO116                MFP_CFG(GPIO116, AF0)
-#define GPIO117_GPIO117                MFP_CFG(GPIO117, AF0)
-#define GPIO118_GPIO118                MFP_CFG(GPIO118, AF0)
-#define GPIO119_GPIO119                MFP_CFG(GPIO119, AF0)
-#define GPIO120_GPIO120                MFP_CFG(GPIO120, AF0)
-#define GPIO121_GPIO121                MFP_CFG(GPIO121, AF0)
-#define GPIO122_GPIO122                MFP_CFG(GPIO122, AF0)
-#define GPIO123_GPIO123                MFP_CFG(GPIO123, AF0)
-#define GPIO124_GPIO124                MFP_CFG(GPIO124, AF0)
-#define GPIO125_GPIO125                MFP_CFG(GPIO125, AF0)
-#define GPIO126_GPIO126                MFP_CFG(GPIO126, AF0)
-#define GPIO127_GPIO127                MFP_CFG(GPIO127, AF0)
-#define GPIO128_GPIO128                MFP_CFG(GPIO128, AF0)
-#define GPIO129_GPIO129                MFP_CFG(GPIO129, AF0)
-#define GPIO130_GPIO130                MFP_CFG(GPIO130, AF0)
-#define GPIO131_GPIO131                MFP_CFG(GPIO131, AF0)
-#define GPIO132_GPIO132                MFP_CFG(GPIO132, AF0)
-#define GPIO133_GPIO133                MFP_CFG(GPIO133, AF0)
-#define GPIO134_GPIO134                MFP_CFG(GPIO134, AF0)
-#define GPIO135_GPIO135                MFP_CFG(GPIO135, AF0)
-#define GPIO136_GPIO136                MFP_CFG(GPIO136, AF0)
-#define GPIO137_GPIO137                MFP_CFG(GPIO137, AF0)
-#define GPIO138_GPIO138                MFP_CFG(GPIO138, AF0)
-#define GPIO139_GPIO139                MFP_CFG(GPIO139, AF0)
-#define GPIO140_GPIO140                MFP_CFG(GPIO140, AF0)
-#define GPIO141_GPIO141                MFP_CFG(GPIO141, AF0)
-#define GPIO142_GPIO142                MFP_CFG(GPIO142, AF1)
-#define GPIO143_GPIO143                MFP_CFG(GPIO143, AF1)
-#define GPIO144_GPIO144                MFP_CFG(GPIO144, AF1)
-#define GPIO145_GPIO145                MFP_CFG(GPIO145, AF1)
-#define GPIO146_GPIO146                MFP_CFG(GPIO146, AF1)
-#define GPIO147_GPIO147                MFP_CFG(GPIO147, AF1)
-#define GPIO148_GPIO148                MFP_CFG(GPIO148, AF1)
-#define GPIO149_GPIO149                MFP_CFG(GPIO149, AF1)
-#define GPIO150_GPIO150                MFP_CFG(GPIO150, AF1)
-#define GPIO151_GPIO151                MFP_CFG(GPIO151, AF1)
-#define GPIO152_GPIO152                MFP_CFG(GPIO152, AF1)
-#define GPIO153_GPIO153                MFP_CFG(GPIO153, AF1)
-#define GPIO154_GPIO154                MFP_CFG(GPIO154, AF1)
-#define GPIO155_GPIO155                MFP_CFG(GPIO155, AF1)
-#define GPIO156_GPIO156                MFP_CFG(GPIO156, AF1)
-#define GPIO157_GPIO157                MFP_CFG(GPIO157, AF1)
-#define GPIO158_GPIO158                MFP_CFG(GPIO158, AF1)
-#define GPIO159_GPIO159                MFP_CFG(GPIO159, AF1)
-#define GPIO160_GPIO160                MFP_CFG(GPIO160, AF1)
-#define GPIO161_GPIO161                MFP_CFG(GPIO161, AF1)
-#define GPIO162_GPIO162                MFP_CFG(GPIO162, AF1)
-#define GPIO163_GPIO163                MFP_CFG(GPIO163, AF1)
-#define GPIO164_GPIO164                MFP_CFG(GPIO164, AF1)
-#define GPIO165_GPIO165                MFP_CFG(GPIO165, AF1)
-#define GPIO166_GPIO166                MFP_CFG(GPIO166, AF1)
-#define GPIO167_GPIO167                MFP_CFG(GPIO167, AF1)
-#define GPIO168_GPIO168                MFP_CFG(GPIO168, AF1)
+#define GPIO0_GPIO     MFP_CFG(GPIO0, AF0)
+#define GPIO1_GPIO     MFP_CFG(GPIO1, AF0)
+#define GPIO2_GPIO     MFP_CFG(GPIO2, AF0)
+#define GPIO3_GPIO     MFP_CFG(GPIO3, AF0)
+#define GPIO4_GPIO     MFP_CFG(GPIO4, AF0)
+#define GPIO5_GPIO     MFP_CFG(GPIO5, AF0)
+#define GPIO6_GPIO     MFP_CFG(GPIO6, AF0)
+#define GPIO7_GPIO     MFP_CFG(GPIO7, AF0)
+#define GPIO8_GPIO     MFP_CFG(GPIO8, AF0)
+#define GPIO9_GPIO     MFP_CFG(GPIO9, AF0)
+#define GPIO10_GPIO    MFP_CFG(GPIO10, AF0)
+#define GPIO11_GPIO    MFP_CFG(GPIO11, AF0)
+#define GPIO12_GPIO    MFP_CFG(GPIO12, AF0)
+#define GPIO13_GPIO    MFP_CFG(GPIO13, AF0)
+#define GPIO14_GPIO    MFP_CFG(GPIO14, AF0)
+#define GPIO15_GPIO    MFP_CFG(GPIO15, AF0)
+#define GPIO16_GPIO    MFP_CFG(GPIO16, AF0)
+#define GPIO17_GPIO    MFP_CFG(GPIO17, AF0)
+#define GPIO18_GPIO    MFP_CFG(GPIO18, AF0)
+#define GPIO19_GPIO    MFP_CFG(GPIO19, AF0)
+#define GPIO20_GPIO    MFP_CFG(GPIO20, AF0)
+#define GPIO21_GPIO    MFP_CFG(GPIO21, AF0)
+#define GPIO22_GPIO    MFP_CFG(GPIO22, AF0)
+#define GPIO23_GPIO    MFP_CFG(GPIO23, AF0)
+#define GPIO24_GPIO    MFP_CFG(GPIO24, AF0)
+#define GPIO25_GPIO    MFP_CFG(GPIO25, AF0)
+#define GPIO26_GPIO    MFP_CFG(GPIO26, AF0)
+#define GPIO27_GPIO    MFP_CFG(GPIO27, AF0)
+#define GPIO28_GPIO    MFP_CFG(GPIO28, AF0)
+#define GPIO29_GPIO    MFP_CFG(GPIO29, AF0)
+#define GPIO30_GPIO    MFP_CFG(GPIO30, AF0)
+#define GPIO31_GPIO    MFP_CFG(GPIO31, AF0)
+#define GPIO32_GPIO    MFP_CFG(GPIO32, AF0)
+#define GPIO33_GPIO    MFP_CFG(GPIO33, AF0)
+#define GPIO34_GPIO    MFP_CFG(GPIO34, AF0)
+#define GPIO35_GPIO    MFP_CFG(GPIO35, AF0)
+#define GPIO36_GPIO    MFP_CFG(GPIO36, AF0)
+#define GPIO37_GPIO    MFP_CFG(GPIO37, AF0)
+#define GPIO38_GPIO    MFP_CFG(GPIO38, AF0)
+#define GPIO39_GPIO    MFP_CFG(GPIO39, AF0)
+#define GPIO40_GPIO    MFP_CFG(GPIO40, AF0)
+#define GPIO41_GPIO    MFP_CFG(GPIO41, AF0)
+#define GPIO42_GPIO    MFP_CFG(GPIO42, AF0)
+#define GPIO43_GPIO    MFP_CFG(GPIO43, AF0)
+#define GPIO44_GPIO    MFP_CFG(GPIO44, AF0)
+#define GPIO45_GPIO    MFP_CFG(GPIO45, AF0)
+#define GPIO46_GPIO    MFP_CFG(GPIO46, AF0)
+#define GPIO47_GPIO    MFP_CFG(GPIO47, AF0)
+#define GPIO48_GPIO    MFP_CFG(GPIO48, AF0)
+#define GPIO49_GPIO    MFP_CFG(GPIO49, AF0)
+#define GPIO50_GPIO    MFP_CFG(GPIO50, AF0)
+#define GPIO51_GPIO    MFP_CFG(GPIO51, AF0)
+#define GPIO52_GPIO    MFP_CFG(GPIO52, AF0)
+#define GPIO53_GPIO    MFP_CFG(GPIO53, AF0)
+#define GPIO54_GPIO    MFP_CFG(GPIO54, AF0)
+#define GPIO55_GPIO    MFP_CFG(GPIO55, AF0)
+#define GPIO56_GPIO    MFP_CFG(GPIO56, AF0)
+#define GPIO57_GPIO    MFP_CFG(GPIO57, AF0)
+#define GPIO58_GPIO    MFP_CFG(GPIO58, AF0)
+#define GPIO59_GPIO    MFP_CFG(GPIO59, AF0)
+#define GPIO60_GPIO    MFP_CFG(GPIO60, AF0)
+#define GPIO61_GPIO    MFP_CFG(GPIO61, AF0)
+#define GPIO62_GPIO    MFP_CFG(GPIO62, AF0)
+#define GPIO63_GPIO    MFP_CFG(GPIO63, AF0)
+#define GPIO64_GPIO    MFP_CFG(GPIO64, AF0)
+#define GPIO65_GPIO    MFP_CFG(GPIO65, AF0)
+#define GPIO66_GPIO    MFP_CFG(GPIO66, AF0)
+#define GPIO67_GPIO    MFP_CFG(GPIO67, AF0)
+#define GPIO68_GPIO    MFP_CFG(GPIO68, AF0)
+#define GPIO69_GPIO    MFP_CFG(GPIO69, AF0)
+#define GPIO70_GPIO    MFP_CFG(GPIO70, AF0)
+#define GPIO71_GPIO    MFP_CFG(GPIO71, AF0)
+#define GPIO72_GPIO    MFP_CFG(GPIO72, AF0)
+#define GPIO73_GPIO    MFP_CFG(GPIO73, AF0)
+#define GPIO74_GPIO    MFP_CFG(GPIO74, AF0)
+#define GPIO75_GPIO    MFP_CFG(GPIO75, AF0)
+#define GPIO76_GPIO    MFP_CFG(GPIO76, AF0)
+#define GPIO77_GPIO    MFP_CFG(GPIO77, AF0)
+#define GPIO78_GPIO    MFP_CFG(GPIO78, AF0)
+#define GPIO79_GPIO    MFP_CFG(GPIO79, AF0)
+#define GPIO80_GPIO    MFP_CFG(GPIO80, AF0)
+#define GPIO81_GPIO    MFP_CFG(GPIO81, AF0)
+#define GPIO82_GPIO    MFP_CFG(GPIO82, AF0)
+#define GPIO83_GPIO    MFP_CFG(GPIO83, AF0)
+#define GPIO84_GPIO    MFP_CFG(GPIO84, AF0)
+#define GPIO85_GPIO    MFP_CFG(GPIO85, AF0)
+#define GPIO86_GPIO    MFP_CFG(GPIO86, AF0)
+#define GPIO87_GPIO    MFP_CFG(GPIO87, AF0)
+#define GPIO88_GPIO    MFP_CFG(GPIO88, AF0)
+#define GPIO89_GPIO    MFP_CFG(GPIO89, AF0)
+#define GPIO90_GPIO    MFP_CFG(GPIO90, AF0)
+#define GPIO91_GPIO    MFP_CFG(GPIO91, AF0)
+#define GPIO92_GPIO    MFP_CFG(GPIO92, AF0)
+#define GPIO93_GPIO    MFP_CFG(GPIO93, AF0)
+#define GPIO94_GPIO    MFP_CFG(GPIO94, AF0)
+#define GPIO95_GPIO    MFP_CFG(GPIO95, AF0)
+#define GPIO96_GPIO    MFP_CFG(GPIO96, AF0)
+#define GPIO97_GPIO    MFP_CFG(GPIO97, AF0)
+#define GPIO98_GPIO    MFP_CFG(GPIO98, AF0)
+#define GPIO99_GPIO    MFP_CFG(GPIO99, AF0)
+#define GPIO100_GPIO   MFP_CFG(GPIO100, AF0)
+#define GPIO101_GPIO   MFP_CFG(GPIO101, AF0)
+#define GPIO102_GPIO   MFP_CFG(GPIO102, AF1)
+#define GPIO103_GPIO   MFP_CFG(GPIO103, AF1)
+#define GPIO104_GPIO   MFP_CFG(GPIO104, AF1)
+#define GPIO105_GPIO   MFP_CFG(GPIO105, AF1)
+#define GPIO106_GPIO   MFP_CFG(GPIO106, AF1)
+#define GPIO107_GPIO   MFP_CFG(GPIO107, AF1)
+#define GPIO108_GPIO   MFP_CFG(GPIO108, AF1)
+#define GPIO109_GPIO   MFP_CFG(GPIO109, AF1)
+#define GPIO110_GPIO   MFP_CFG(GPIO110, AF1)
+#define GPIO111_GPIO   MFP_CFG(GPIO111, AF1)
+#define GPIO112_GPIO   MFP_CFG(GPIO112, AF1)
+#define GPIO113_GPIO   MFP_CFG(GPIO113, AF1)
+#define GPIO114_GPIO   MFP_CFG(GPIO114, AF0)
+#define GPIO115_GPIO   MFP_CFG(GPIO115, AF0)
+#define GPIO116_GPIO   MFP_CFG(GPIO116, AF0)
+#define GPIO117_GPIO   MFP_CFG(GPIO117, AF0)
+#define GPIO118_GPIO   MFP_CFG(GPIO118, AF0)
+#define GPIO119_GPIO   MFP_CFG(GPIO119, AF0)
+#define GPIO120_GPIO   MFP_CFG(GPIO120, AF0)
+#define GPIO121_GPIO   MFP_CFG(GPIO121, AF0)
+#define GPIO122_GPIO   MFP_CFG(GPIO122, AF0)
+#define GPIO123_GPIO   MFP_CFG(GPIO123, AF0)
+#define GPIO124_GPIO   MFP_CFG(GPIO124, AF0)
+#define GPIO125_GPIO   MFP_CFG(GPIO125, AF0)
+#define GPIO126_GPIO   MFP_CFG(GPIO126, AF0)
+#define GPIO127_GPIO   MFP_CFG(GPIO127, AF0)
+#define GPIO128_GPIO   MFP_CFG(GPIO128, AF0)
+#define GPIO129_GPIO   MFP_CFG(GPIO129, AF0)
+#define GPIO130_GPIO   MFP_CFG(GPIO130, AF0)
+#define GPIO131_GPIO   MFP_CFG(GPIO131, AF0)
+#define GPIO132_GPIO   MFP_CFG(GPIO132, AF0)
+#define GPIO133_GPIO   MFP_CFG(GPIO133, AF0)
+#define GPIO134_GPIO   MFP_CFG(GPIO134, AF0)
+#define GPIO135_GPIO   MFP_CFG(GPIO135, AF0)
+#define GPIO136_GPIO   MFP_CFG(GPIO136, AF0)
+#define GPIO137_GPIO   MFP_CFG(GPIO137, AF0)
+#define GPIO138_GPIO   MFP_CFG(GPIO138, AF0)
+#define GPIO139_GPIO   MFP_CFG(GPIO139, AF0)
+#define GPIO140_GPIO   MFP_CFG(GPIO140, AF0)
+#define GPIO141_GPIO   MFP_CFG(GPIO141, AF0)
+#define GPIO142_GPIO   MFP_CFG(GPIO142, AF1)
+#define GPIO143_GPIO   MFP_CFG(GPIO143, AF1)
+#define GPIO144_GPIO   MFP_CFG(GPIO144, AF1)
+#define GPIO145_GPIO   MFP_CFG(GPIO145, AF1)
+#define GPIO146_GPIO   MFP_CFG(GPIO146, AF1)
+#define GPIO147_GPIO   MFP_CFG(GPIO147, AF1)
+#define GPIO148_GPIO   MFP_CFG(GPIO148, AF1)
+#define GPIO149_GPIO   MFP_CFG(GPIO149, AF1)
+#define GPIO150_GPIO   MFP_CFG(GPIO150, AF1)
+#define GPIO151_GPIO   MFP_CFG(GPIO151, AF1)
+#define GPIO152_GPIO   MFP_CFG(GPIO152, AF1)
+#define GPIO153_GPIO   MFP_CFG(GPIO153, AF1)
+#define GPIO154_GPIO   MFP_CFG(GPIO154, AF1)
+#define GPIO155_GPIO   MFP_CFG(GPIO155, AF1)
+#define GPIO156_GPIO   MFP_CFG(GPIO156, AF1)
+#define GPIO157_GPIO   MFP_CFG(GPIO157, AF1)
+#define GPIO158_GPIO   MFP_CFG(GPIO158, AF1)
+#define GPIO159_GPIO   MFP_CFG(GPIO159, AF1)
+#define GPIO160_GPIO   MFP_CFG(GPIO160, AF1)
+#define GPIO161_GPIO   MFP_CFG(GPIO161, AF1)
+#define GPIO162_GPIO   MFP_CFG(GPIO162, AF1)
+#define GPIO163_GPIO   MFP_CFG(GPIO163, AF1)
+#define GPIO164_GPIO   MFP_CFG(GPIO164, AF1)
+#define GPIO165_GPIO   MFP_CFG(GPIO165, AF1)
+#define GPIO166_GPIO   MFP_CFG(GPIO166, AF1)
+#define GPIO167_GPIO   MFP_CFG(GPIO167, AF1)
+#define GPIO168_GPIO   MFP_CFG(GPIO168, AF1)
 
 /* DFI */
 #define GPIO108_DFI_D15                MFP_CFG(GPIO108, AF0)
index dbba6e8a60c41487e3cf4e61cecf9ef6c8231ea9..4aec493640b41c1656bbdded16c1b55e0c2f4f60 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_MACH_MMP2_H
 #define __ASM_MACH_MMP2_H
 
+#include <plat/sdhci.h>
+
 struct sys_timer;
 
 extern struct sys_timer mmp2_timer;
@@ -22,6 +24,10 @@ extern struct pxa_device_desc mmp2_device_twsi3;
 extern struct pxa_device_desc mmp2_device_twsi4;
 extern struct pxa_device_desc mmp2_device_twsi5;
 extern struct pxa_device_desc mmp2_device_twsi6;
+extern struct pxa_device_desc mmp2_device_sdh0;
+extern struct pxa_device_desc mmp2_device_sdh1;
+extern struct pxa_device_desc mmp2_device_sdh2;
+extern struct pxa_device_desc mmp2_device_sdh3;
 
 static inline int mmp2_add_uart(int id)
 {
@@ -63,5 +69,21 @@ static inline int mmp2_add_twsi(int id, struct i2c_pxa_platform_data *data,
        return pxa_register_device(d, data, sizeof(*data));
 }
 
+static inline int mmp2_add_sdhost(int id, struct sdhci_pxa_platdata *data)
+{
+       struct pxa_device_desc *d = NULL;
+
+       switch (id) {
+       case 0: d = &mmp2_device_sdh0; break;
+       case 1: d = &mmp2_device_sdh1; break;
+       case 2: d = &mmp2_device_sdh2; break;
+       case 3: d = &mmp2_device_sdh3; break;
+       default:
+               return -EINVAL;
+       }
+
+       return pxa_register_device(d, data, sizeof(*data));
+}
+
 #endif /* __ASM_MACH_MMP2_H */
 
index ac4702357a6e5b026d8939bdd93fdad9c2ed2c6d..f7011ef70bf5e2565bd0fc508ffd66fa681cff7b 100644 (file)
@@ -27,6 +27,8 @@
 #define APMU_DMA       APMU_REG(0x064)
 #define APMU_GEU       APMU_REG(0x068)
 #define APMU_BUS       APMU_REG(0x06c)
+#define APMU_SDH2      APMU_REG(0x0e8)
+#define APMU_SDH3      APMU_REG(0x0ec)
 
 #define APMU_FNCLK_EN  (1 << 4)
 #define APMU_AXICLK_EN (1 << 3)
index 2a684fa50773cebc8a57e1d470840f1bfd5d8d31..24172a0aad59a53a7e8f55b293ade8a01144d006 100644 (file)
@@ -67,6 +67,36 @@ static unsigned long jasper_pin_config[] __initdata = {
 
        /* PMIC */
        PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
+
+       /* MMC1 */
+       GPIO131_MMC1_DAT3,
+       GPIO132_MMC1_DAT2,
+       GPIO133_MMC1_DAT1,
+       GPIO134_MMC1_DAT0,
+       GPIO136_MMC1_CMD,
+       GPIO139_MMC1_CLK,
+       GPIO140_MMC1_CD,
+       GPIO141_MMC1_WP,
+
+       /* MMC2 */
+       GPIO37_MMC2_DAT3,
+       GPIO38_MMC2_DAT2,
+       GPIO39_MMC2_DAT1,
+       GPIO40_MMC2_DAT0,
+       GPIO41_MMC2_CMD,
+       GPIO42_MMC2_CLK,
+
+       /* MMC3 */
+       GPIO165_MMC3_DAT7,
+       GPIO162_MMC3_DAT6,
+       GPIO166_MMC3_DAT5,
+       GPIO163_MMC3_DAT4,
+       GPIO167_MMC3_DAT3,
+       GPIO164_MMC3_DAT2,
+       GPIO168_MMC3_DAT1,
+       GPIO111_MMC3_DAT0,
+       GPIO112_MMC3_CMD,
+       GPIO151_MMC3_CLK,
 };
 
 static struct regulator_consumer_supply max8649_supply[] = {
@@ -123,6 +153,10 @@ static struct i2c_board_info jasper_twsi1_info[] = {
        },
 };
 
+static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
+       .max_speed      = 25000000,
+};
+
 static void __init jasper_init(void)
 {
        mfp_config(ARRAY_AND_SIZE(jasper_pin_config));
@@ -131,6 +165,7 @@ static void __init jasper_init(void)
        mmp2_add_uart(1);
        mmp2_add_uart(3);
        mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(jasper_twsi1_info));
+       mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
 
        regulator_has_full_constraints();
 }
index daf3993349f81986fa8f5b90ca0c4bcb4e7acc8a..8e6c3ac7f7c17fd275191caf83840e80406896ef 100644 (file)
@@ -115,6 +115,29 @@ void __init mmp2_init_irq(void)
        mmp2_init_gpio();
 }
 
+static void sdhc_clk_enable(struct clk *clk)
+{
+       uint32_t clk_rst;
+
+       clk_rst  =  __raw_readl(clk->clk_rst);
+       clk_rst |= clk->enable_val;
+       __raw_writel(clk_rst, clk->clk_rst);
+}
+
+static void sdhc_clk_disable(struct clk *clk)
+{
+       uint32_t clk_rst;
+
+       clk_rst  =  __raw_readl(clk->clk_rst);
+       clk_rst &= ~clk->enable_val;
+       __raw_writel(clk_rst, clk->clk_rst);
+}
+
+struct clkops sdhc_clk_ops = {
+       .enable         = sdhc_clk_enable,
+       .disable        = sdhc_clk_disable,
+};
+
 /* APB peripheral clocks */
 static APBC_CLK(uart1, MMP2_UART1, 1, 26000000);
 static APBC_CLK(uart2, MMP2_UART2, 1, 26000000);
@@ -126,9 +149,12 @@ static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000);
 static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000);
 static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000);
 static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000);
-static APBC_CLK(rtc, MMP2_RTC, 0, 32768);
 
 static APMU_CLK(nand, NAND, 0xbf, 100000000);
+static APMU_CLK_OPS(sdh0, SDH0, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh1, SDH1, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh2, SDH2, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh3, SDH3, 0x1b, 200000000, &sdhc_clk_ops);
 
 static struct clk_lookup mmp2_clkregs[] = {
        INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
@@ -142,6 +168,10 @@ static struct clk_lookup mmp2_clkregs[] = {
        INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
        INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
        INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+       INIT_CLKREG(&clk_sdh0, "sdhci-pxa.0", "PXA-SDHCLK"),
+       INIT_CLKREG(&clk_sdh1, "sdhci-pxa.1", "PXA-SDHCLK"),
+       INIT_CLKREG(&clk_sdh2, "sdhci-pxa.2", "PXA-SDHCLK"),
+       INIT_CLKREG(&clk_sdh3, "sdhci-pxa.3", "PXA-SDHCLK"),
 };
 
 static int __init mmp2_init(void)
@@ -192,4 +222,8 @@ MMP2_DEVICE(twsi4, "pxa2xx-i2c", 3, TWSI4, 0xd4033000, 0x70);
 MMP2_DEVICE(twsi5, "pxa2xx-i2c", 4, TWSI5, 0xd4033800, 0x70);
 MMP2_DEVICE(twsi6, "pxa2xx-i2c", 5, TWSI6, 0xd4034000, 0x70);
 MMP2_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x100, 28, 29);
+MMP2_DEVICE(sdh0, "sdhci-pxa", 0, MMC, 0xd4280000, 0x120);
+MMP2_DEVICE(sdh1, "sdhci-pxa", 1, MMC2, 0xd4280800, 0x120);
+MMP2_DEVICE(sdh2, "sdhci-pxa", 2, MMC3, 0xd4281000, 0x120);
+MMP2_DEVICE(sdh3, "sdhci-pxa", 3, MMC4, 0xd4281800, 0x120);
 
index 46f2d69bef3cf01dd3778a380fa2b1801799cef1..8f92ccd26edf9f77457d34f7429fb9182dd5e62d 100644 (file)
@@ -111,6 +111,7 @@ static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
 static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
 
 static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(u2o, USB, 0x1b, 480000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa910_clkregs[] = {
@@ -123,6 +124,7 @@ static struct clk_lookup pxa910_clkregs[] = {
        INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL),
        INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
        INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+       INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"),
 };
 
 static int __init pxa910_init(void)
index dbbcfeb919db44bd12ff98605561198f16f118c5..31e5fd63ec9a1cad215e329e0bf47c477135808d 100644 (file)
@@ -49,6 +49,8 @@ endchoice
 
 config MSM_SOC_REV_A
        bool
+config  ARCH_MSM_SCORPIONMP
+       bool
 
 config  ARCH_MSM_ARM11
        bool
index 788bdace13048a55192303d31d243b8521a79d93..3eff39921d4d7cbfde85a6343a1f0c2db7701b32 100644 (file)
@@ -65,7 +65,7 @@
  */
 #define DDR_VIRT_BASE          (MV78XX0_REGS_VIRT_BASE | 0x00000)
 #define  DDR_WINDOW_CPU0_BASE  (DDR_VIRT_BASE | 0x1500)
-#define  DDR_WINDOW_CPU1_BASE  (DDR_VIRT_BASE | 0x1700)
+#define  DDR_WINDOW_CPU1_BASE  (DDR_VIRT_BASE | 0x1570)
 
 #define DEV_BUS_PHYS_BASE      (MV78XX0_REGS_PHYS_BASE | 0x10000)
 #define DEV_BUS_VIRT_BASE      (MV78XX0_REGS_VIRT_BASE | 0x10000)
index 86c9b210295214c175638df2997745d2643cd447..9db9203667df504c5b5731680b3f75077ae79b6d 100644 (file)
@@ -216,7 +216,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "wl1271",
                .mmc            = 3,
-               .caps           = MMC_CAP_4_BIT_DATA,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
                .gpio_wp        = -EINVAL,
                .gpio_cd        = -EINVAL,
                .nonremovable   = true,
index 40562ddd3ee4fe29ea1e173a61d778225d28b01d..a1939b1e6f82e0d30ca77b8b4156c27eb6f1c4ce 100644 (file)
@@ -297,7 +297,7 @@ static int __init _omap2_init_reprogram_sdrc(void)
                return 0;
 
        dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
-       if (!dpll3_m2_ck)
+       if (IS_ERR(dpll3_m2_ck))
                return -EINVAL;
 
        rate = clk_get_rate(dpll3_m2_ck);
index 5e81517a7af2040a8bff6a2e2eabc9a96e300b76..a8afb610c7d83fa7a500445ea4647d4935d26e09 100644 (file)
@@ -161,6 +161,23 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
                printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
 }
 
+void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
+{
+       u32 tick_rate, cycles;
+
+       if (!seconds && !milliseconds)
+               return;
+
+       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
+       omap_dm_timer_stop(gptimer_wakeup);
+       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+       pr_info("PM: Resume timer in %u.%03u secs"
+               " (%d ticks at %d ticks/sec.)\n",
+               seconds, milliseconds, cycles, tick_rate);
+}
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -354,23 +371,6 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
        pwrdm->timer = t;
 }
 
-void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-       u32 tick_rate, cycles;
-
-       if (!seconds && !milliseconds)
-               return;
-
-       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-       omap_dm_timer_stop(gptimer_wakeup);
-       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-       pr_info("PM: Resume timer in %u.%03u secs"
-               " (%d ticks at %d ticks/sec.)\n",
-               seconds, milliseconds, cycles, tick_rate);
-}
-
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
        struct seq_file *s = (struct seq_file *)user;
index c85923e56b85e350b97b027d9a8352e9a8b6776b..aaeea49b9bdd80f6e51affaee9c3a38ff6e2368f 100644 (file)
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
 
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state = PM_SUSPEND_ON;
+static inline bool is_suspending(void)
+{
+       return (suspend_state != PM_SUSPEND_ON);
+}
+#else
+static inline bool is_suspending(void)
+{
+       return false;
+}
+#endif
+
 static void (*omap2_sram_idle)(void);
 static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
                                  void __iomem *sdrc_power);
@@ -120,8 +133,9 @@ static void omap2_enter_full_retention(void)
                goto no_sleep;
 
        /* Block console output in case it is on one of the OMAP UARTs */
-       if (try_acquire_console_sem())
-               goto no_sleep;
+       if (!is_suspending())
+               if (try_acquire_console_sem())
+                       goto no_sleep;
 
        omap_uart_prepare_idle(0);
        omap_uart_prepare_idle(1);
@@ -136,7 +150,8 @@ static void omap2_enter_full_retention(void)
        omap_uart_resume_idle(1);
        omap_uart_resume_idle(0);
 
-       release_console_sem();
+       if (!is_suspending())
+               release_console_sem();
 
 no_sleep:
        if (omap2_pm_debug) {
@@ -284,6 +299,12 @@ out:
        local_irq_enable();
 }
 
+static int omap2_pm_begin(suspend_state_t state)
+{
+       suspend_state = state;
+       return 0;
+}
+
 static int omap2_pm_prepare(void)
 {
        /* We cannot sleep in idle until we have resumed */
@@ -333,10 +354,17 @@ static void omap2_pm_finish(void)
        enable_hlt();
 }
 
+static void omap2_pm_end(void)
+{
+       suspend_state = PM_SUSPEND_ON;
+}
+
 static struct platform_suspend_ops omap_pm_ops = {
+       .begin          = omap2_pm_begin,
        .prepare        = omap2_pm_prepare,
        .enter          = omap2_pm_enter,
        .finish         = omap2_pm_finish,
+       .end            = omap2_pm_end,
        .valid          = suspend_valid_only_mem,
 };
 
index 0ec8a04b74730bfccc3e0d709c493e9d8ac8e256..648b8c50d02422eeda2146cf3d3ebbe4b44d5a75 100644 (file)
 #include "sdrc.h"
 #include "control.h"
 
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state = PM_SUSPEND_ON;
+static inline bool is_suspending(void)
+{
+       return (suspend_state != PM_SUSPEND_ON);
+}
+#else
+static inline bool is_suspending(void)
+{
+       return false;
+}
+#endif
+
 /* Scratchpad offsets */
 #define OMAP343X_TABLE_ADDRESS_OFFSET     0xc4
 #define OMAP343X_TABLE_VALUE_OFFSET       0xc0
@@ -387,10 +400,11 @@ void omap_sram_idle(void)
        }
 
        /* Block console output in case it is on one of the OMAP UARTs */
-       if (per_next_state < PWRDM_POWER_ON ||
-           core_next_state < PWRDM_POWER_ON)
-               if (try_acquire_console_sem())
-                       goto console_still_active;
+       if (!is_suspending())
+               if (per_next_state < PWRDM_POWER_ON ||
+                   core_next_state < PWRDM_POWER_ON)
+                       if (try_acquire_console_sem())
+                               goto console_still_active;
 
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
@@ -470,7 +484,8 @@ void omap_sram_idle(void)
                omap_uart_resume_idle(3);
        }
 
-       release_console_sem();
+       if (!is_suspending())
+               release_console_sem();
 
 console_still_active:
        /* Disable IO-PAD and IO-CHAIN wakeup */
@@ -514,8 +529,6 @@ out:
 }
 
 #ifdef CONFIG_SUSPEND
-static suspend_state_t suspend_state;
-
 static int omap3_pm_prepare(void)
 {
        disable_hlt();
index 298a22a754e20a56e428aeaed051cdd7b2b923f7..f81acee4738dea03f64576b6a6288282002def39 100644 (file)
 #define OMAP24XX_EN_GPT1_MASK                          (1 << 0)
 
 /* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */
-#define OMAP24XX_ST_GPIOS_SHIFT                                (1 << 2)
-#define OMAP24XX_ST_GPIOS_MASK                         2
-#define OMAP24XX_ST_GPT1_SHIFT                         (1 << 0)
-#define OMAP24XX_ST_GPT1_MASK                          0
+#define OMAP24XX_ST_GPIOS_SHIFT                                2
+#define OMAP24XX_ST_GPIOS_MASK                         (1 << 2)
+#define OMAP24XX_ST_GPT1_SHIFT                         0
+#define OMAP24XX_ST_GPT1_MASK                          (1 << 0)
 
 /* CM_IDLEST_MDM and PM_WKST_MDM shared bits */
-#define OMAP2430_ST_MDM_SHIFT                          (1 << 0)
+#define OMAP2430_ST_MDM_SHIFT                          0
+#define OMAP2430_ST_MDM_MASK                           (1 << 0)
 
 
 /* 3430 register bits shared between CM & PRM registers */
index c897e03e413d05eb91c836d0472d9534f71633f7..6604fc6ca58a577137ba4f28824370b7ee894594 100644 (file)
@@ -51,6 +51,13 @@ config MACH_LINKSTATION_PRO
          Buffalo Linkstation Pro/Live platform. Both v1 and
          v2 devices are supported.
 
+config MACH_LINKSTATION_LSCHL
+       bool "Buffalo Linkstation Live v3 (LS-CHL)"
+       select I2C_BOARDINFO
+       help
+         Say 'Y' here if you want your kernel to support the
+         Buffalo Linkstation Live v3 (LS-CHL) platform.
+
 config MACH_LINKSTATION_MINI
        bool "Buffalo Linkstation Mini"
        select I2C_BOARDINFO
index eb6eabcb41e4526275fe0c8973d3d3c746fa7c97..7f18cdacd4873fb43b201a72534e52fb07c8680f 100644 (file)
@@ -21,3 +21,4 @@ obj-$(CONFIG_MACH_WNR854T)    += wnr854t-setup.o
 obj-$(CONFIG_MACH_RD88F5181L_GE)       += rd88f5181l-ge-setup.o
 obj-$(CONFIG_MACH_RD88F5181L_FXO)      += rd88f5181l-fxo-setup.o
 obj-$(CONFIG_MACH_RD88F6183AP_GE)      += rd88f6183ap-ge-setup.o
+obj-$(CONFIG_MACH_LINKSTATION_LSCHL)   += ls-chl-setup.o
diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
new file mode 100644 (file)
index 0000000..20a9b66
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * arch/arm/mach-orion5x/ls-chl-setup.c
+ *
+ * Maintainer: Ash Hughes <ashley.hughes@blueyonder.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/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/leds.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio-fan.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/ata_platform.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/system.h>
+#include <mach/orion5x.h>
+#include "common.h"
+#include "mpp.h"
+
+/*****************************************************************************
+ * Linkstation LS-CHL Info
+ ****************************************************************************/
+
+/*
+ * 256K NOR flash Device bus boot chip select
+ */
+
+#define LSCHL_NOR_BOOT_BASE    0xf4000000
+#define LSCHL_NOR_BOOT_SIZE    SZ_256K
+
+/*****************************************************************************
+ * 256KB NOR Flash on BOOT Device
+ ****************************************************************************/
+
+static struct physmap_flash_data lschl_nor_flash_data = {
+       .width = 1,
+};
+
+static struct resource lschl_nor_flash_resource = {
+       .flags  = IORESOURCE_MEM,
+       .start  = LSCHL_NOR_BOOT_BASE,
+       .end    = LSCHL_NOR_BOOT_BASE + LSCHL_NOR_BOOT_SIZE - 1,
+};
+
+static struct platform_device lschl_nor_flash = {
+       .name = "physmap-flash",
+       .id = 0,
+       .dev = {
+               .platform_data  = &lschl_nor_flash_data,
+       },
+       .num_resources = 1,
+       .resource = &lschl_nor_flash_resource,
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data lschl_eth_data = {
+       .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * RTC 5C372a on I2C bus
+ ****************************************************************************/
+
+static struct i2c_board_info __initdata lschl_i2c_rtc = {
+       I2C_BOARD_INFO("rs5c372a", 0x32),
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+
+#define LSCHL_GPIO_LED_ALARM   2
+#define LSCHL_GPIO_LED_INFO    3
+#define LSCHL_GPIO_LED_FUNC    17
+#define LSCHL_GPIO_LED_PWR     0
+
+static struct gpio_led lschl_led_pins[] = {
+       {
+               .name = "alarm:red",
+               .gpio = LSCHL_GPIO_LED_ALARM,
+               .active_low = 1,
+       }, {
+               .name = "info:amber",
+               .gpio = LSCHL_GPIO_LED_INFO,
+               .active_low = 1,
+       }, {
+               .name = "func:blue:top",
+               .gpio = LSCHL_GPIO_LED_FUNC,
+               .active_low = 1,
+       }, {
+               .name = "power:blue:bottom",
+               .gpio = LSCHL_GPIO_LED_PWR,
+       },
+};
+
+static struct gpio_led_platform_data lschl_led_data = {
+       .leds = lschl_led_pins,
+       .num_leds = ARRAY_SIZE(lschl_led_pins),
+};
+
+static struct platform_device lschl_leds = {
+       .name = "leds-gpio",
+       .id = -1,
+       .dev = {
+               .platform_data = &lschl_led_data,
+       },
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data lschl_sata_data = {
+       .n_ports = 2,
+};
+
+/*****************************************************************************
+ * LS-CHL specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the LS-CHL, the shutdown process is following:
+ * - Userland monitors key events until the power switch goes to off position
+ * - The board reboots
+ * - U-boot starts and goes into an idle mode waiting for the user
+ *   to move the switch to ON position
+ *
+ */
+
+static void lschl_power_off(void)
+{
+       arm_machine_restart('h', NULL);
+}
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+#define LSCHL_GPIO_USB_POWER   9
+#define LSCHL_GPIO_AUTO_POWER  17
+#define LSCHL_GPIO_POWER       18
+
+/****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+#define LSCHL_GPIO_KEY_FUNC            15
+#define LSCHL_GPIO_KEY_POWER           8
+#define LSCHL_GPIO_KEY_AUTOPOWER       10
+#define LSCHL_SW_POWER         0x00
+#define LSCHL_SW_AUTOPOWER     0x01
+#define LSCHL_SW_FUNC          0x02
+
+static struct gpio_keys_button lschl_buttons[] = {
+       {
+               .type = EV_SW,
+               .code = LSCHL_SW_POWER,
+               .gpio = LSCHL_GPIO_KEY_POWER,
+               .desc = "Power-on Switch",
+               .active_low = 1,
+       }, {
+               .type = EV_SW,
+               .code = LSCHL_SW_AUTOPOWER,
+               .gpio = LSCHL_GPIO_KEY_AUTOPOWER,
+               .desc = "Power-auto Switch",
+               .active_low = 1,
+       }, {
+               .type = EV_SW,
+               .code = LSCHL_SW_FUNC,
+               .gpio = LSCHL_GPIO_KEY_FUNC,
+               .desc = "Function Switch",
+               .active_low = 1,
+       },
+};
+
+static struct gpio_keys_platform_data lschl_button_data = {
+       .buttons = lschl_buttons,
+       .nbuttons = ARRAY_SIZE(lschl_buttons),
+};
+
+static struct platform_device lschl_button_device = {
+       .name = "gpio-keys",
+       .id = -1,
+       .num_resources = 0,
+       .dev = {
+               .platform_data = &lschl_button_data,
+       },
+};
+
+#define LSCHL_GPIO_HDD_POWER   1
+
+/****************************************************************************
+ * GPIO Fan
+ ****************************************************************************/
+
+#define LSCHL_GPIO_FAN_LOW     16
+#define LSCHL_GPIO_FAN_HIGH    14
+#define LSCHL_GPIO_FAN_LOCK    6
+
+static struct gpio_fan_alarm lschl_alarm = {
+       .gpio = LSCHL_GPIO_FAN_LOCK,
+};
+
+static struct gpio_fan_speed lschl_speeds[] = {
+       {
+               .rpm = 0,
+               .ctrl_val = 3,
+       }, {
+               .rpm = 1500,
+               .ctrl_val = 2,
+       }, {
+               .rpm = 3250,
+               .ctrl_val = 1,
+       }, {
+               .rpm = 5000,
+               .ctrl_val = 0,
+       },
+};
+
+static int lschl_gpio_list[] = {
+       LSCHL_GPIO_FAN_HIGH, LSCHL_GPIO_FAN_LOW,
+};
+
+static struct gpio_fan_platform_data lschl_fan_data = {
+       .num_ctrl = ARRAY_SIZE(lschl_gpio_list),
+       .ctrl = lschl_gpio_list,
+       .alarm = &lschl_alarm,
+       .num_speed = ARRAY_SIZE(lschl_speeds),
+       .speed = lschl_speeds,
+};
+
+static struct platform_device lschl_fan_device = {
+       .name = "gpio-fan",
+       .id = -1,
+       .num_resources = 0,
+       .dev = {
+               .platform_data = &lschl_fan_data,
+       },
+};
+
+/****************************************************************************
+ * GPIO Data
+ ****************************************************************************/
+
+static struct orion5x_mpp_mode lschl_mpp_modes[] __initdata = {
+       {  0, MPP_GPIO }, /* LED POWER */
+       {  1, MPP_GPIO }, /* HDD POWER */
+       {  2, MPP_GPIO }, /* LED ALARM */
+       {  3, MPP_GPIO }, /* LED INFO */
+       {  4, MPP_UNUSED },
+       {  5, MPP_UNUSED },
+       {  6, MPP_GPIO }, /* FAN LOCK */
+       {  7, MPP_GPIO }, /* SW INIT */
+       {  8, MPP_GPIO }, /* SW POWER */
+       {  9, MPP_GPIO }, /* USB POWER */
+       { 10, MPP_GPIO }, /* SW AUTO POWER */
+       { 11, MPP_UNUSED },
+       { 12, MPP_UNUSED },
+       { 13, MPP_UNUSED },
+       { 14, MPP_GPIO }, /* FAN HIGH */
+       { 15, MPP_GPIO }, /* SW FUNC */
+       { 16, MPP_GPIO }, /* FAN LOW */
+       { 17, MPP_GPIO }, /* LED FUNC */
+       { 18, MPP_UNUSED },
+       { 19, MPP_UNUSED },
+       { -1 },
+};
+
+static void __init lschl_init(void)
+{
+       /*
+        * Setup basic Orion functions. Needs to be called early.
+        */
+       orion5x_init();
+
+       orion5x_mpp_conf(lschl_mpp_modes);
+
+       /*
+        * Configure peripherals.
+        */
+       orion5x_ehci0_init();
+       orion5x_ehci1_init();
+       orion5x_eth_init(&lschl_eth_data);
+       orion5x_i2c_init();
+       orion5x_sata_init(&lschl_sata_data);
+       orion5x_uart0_init();
+       orion5x_xor_init();
+
+       orion5x_setup_dev_boot_win(LSCHL_NOR_BOOT_BASE,
+                                  LSCHL_NOR_BOOT_SIZE);
+       platform_device_register(&lschl_nor_flash);
+
+       platform_device_register(&lschl_leds);
+
+       platform_device_register(&lschl_button_device);
+
+       platform_device_register(&lschl_fan_device);
+
+       i2c_register_board_info(0, &lschl_i2c_rtc, 1);
+
+       /* usb power on */
+       gpio_set_value(LSCHL_GPIO_USB_POWER, 1);
+
+       /* register power-off method */
+       pm_power_off = lschl_power_off;
+
+       pr_info("%s: finished\n", __func__);
+}
+
+MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
+       /* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
+       .boot_params    = 0x00000100,
+       .init_machine   = lschl_init,
+       .map_io         = orion5x_map_io,
+       .init_irq       = orion5x_init_irq,
+       .timer          = &orion5x_timer,
+       .fixup          = tag_fixup_mem32,
+MACHINE_END
index dd235ecc9d6c5946d6610bb7adef42cb57476210..1df6db6a136e0f90aff94166235bcafe02ddd477 100644 (file)
@@ -50,6 +50,10 @@ config MACH_SAAR
        select PXA3xx
        select CPU_PXA930
 
+config MACH_SAARB
+       bool "PXA955 Handheld Platform (aka SAARB)"
+       select CPU_PXA955
+
 comment "Third Party Dev Platforms (sorted by vendor name)"
 
 config ARCH_PXA_IDP
@@ -232,10 +236,6 @@ config MACH_COLIBRI
        bool "Toradex Colibri PXA270"
        select PXA27x
 
-config MACH_COLIBRI_PXA270_EVALBOARD
-       bool "Toradex Colibri Evaluation Carrier Board support (PXA270)"
-       depends on MACH_COLIBRI
-
 config MACH_COLIBRI_PXA270_INCOME
        bool "Income s.r.o. PXA270 SBC"
        depends on MACH_COLIBRI
@@ -253,6 +253,10 @@ config MACH_COLIBRI320
        select PXA3xx
        select CPU_PXA320
 
+config MACH_COLIBRI_EVALBOARD
+       bool "Toradex Colibri Evaluation Carrier Board support"
+       depends on MACH_COLIBRI || MACH_COLIBRI300 || MACH_COLIBRI320
+
 config MACH_VPAC270
        bool "Voipac PXA270"
        select PXA27x
@@ -651,11 +655,17 @@ config CPU_PXA935
        help
          PXA935 (codename Tavor-P65)
 
-config CPU_PXA950
+config PXA95x
        bool
-       select CPU_PXA930
+       select CPU_PJ4
+       help
+         Select code specific to PXA95x variants
+
+config CPU_PXA955
+       bool
+       select PXA95x
        help
-         PXA950 (codename Tavor-PV2)
+         PXA950 (codename MG1)
 
 config PXA_SHARP_C7xx
        bool
index e2f89c2c6f4962ea38a98ea9adb6e3dca8e63ed9..cc39d17b2e078e288231952a606828a9801a7ad5 100644 (file)
@@ -16,9 +16,10 @@ endif
 # Generic drivers that other drivers may depend upon
 
 # SoC-specific code
-obj-$(CONFIG_PXA25x)           += mfp-pxa2xx.o pxa2xx.o pxa25x.o
-obj-$(CONFIG_PXA27x)           += mfp-pxa2xx.o pxa2xx.o pxa27x.o
-obj-$(CONFIG_PXA3xx)           += mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
+obj-$(CONFIG_PXA25x)           += mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa25x.o
+obj-$(CONFIG_PXA27x)           += mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa27x.o
+obj-$(CONFIG_PXA3xx)           += mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
+obj-$(CONFIG_PXA95x)           += mfp-pxa3xx.o clock-pxa3xx.o pxa95x.o smemc.o
 obj-$(CONFIG_CPU_PXA300)       += pxa300.o
 obj-$(CONFIG_CPU_PXA320)       += pxa320.o
 obj-$(CONFIG_CPU_PXA930)       += pxa930.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_MACH_LITTLETON)  += littleton.o
 obj-$(CONFIG_MACH_TAVOREVB)    += tavorevb.o
 obj-$(CONFIG_MACH_TAVOREVB3)   += tavorevb3.o
 obj-$(CONFIG_MACH_SAAR)                += saar.o
+obj-$(CONFIG_MACH_SAARB)       += saarb.o
 
 # 3rd Party Dev Platforms
 obj-$(CONFIG_ARCH_PXA_IDP)     += idp.o
@@ -60,7 +62,7 @@ obj-$(CONFIG_MACH_LOGICPD_PXA270)     += lpd270.o
 obj-$(CONFIG_MACH_PCM027)              += pcm027.o
 obj-$(CONFIG_MACH_PCM990_BASEBOARD)    += pcm990-baseboard.o
 obj-$(CONFIG_MACH_COLIBRI)                     += colibri-pxa270.o
-obj-$(CONFIG_MACH_COLIBRI_PXA270_EVALBOARD)    += colibri-pxa270-evalboard.o
+obj-$(CONFIG_MACH_COLIBRI_EVALBOARD)   += colibri-evalboard.o
 obj-$(CONFIG_MACH_COLIBRI_PXA270_INCOME)       += colibri-pxa270-income.o
 obj-$(CONFIG_MACH_COLIBRI300)  += colibri-pxa3xx.o colibri-pxa300.o
 obj-$(CONFIG_MACH_COLIBRI320)  += colibri-pxa3xx.o colibri-pxa320.o
index 21e188901935fc4f5e4c6b56b58161ed40ac5ab9..ccb2d0cebcc3bb2c857391aadc3632f1da63d78a 100644 (file)
@@ -567,27 +567,29 @@ static inline void balloon3_i2c_init(void) {}
  * NAND
  ******************************************************************************/
 #if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
-static uint16_t balloon3_ctl =
-       BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
-       BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
-       BALLOON3_NAND_CONTROL_FLWP;
-
 static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
        struct nand_chip *this = mtd->priv;
+       uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;
 
        if (ctrl & NAND_CTRL_CHANGE) {
                if (ctrl & NAND_CLE)
-                       balloon3_ctl |= BALLOON3_NAND_CONTROL_FLCLE;
+                       balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLCLE;
                else
-                       balloon3_ctl &= ~BALLOON3_NAND_CONTROL_FLCLE;
+                       balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLCLE;
 
                if (ctrl & NAND_ALE)
-                       balloon3_ctl |= BALLOON3_NAND_CONTROL_FLALE;
+                       balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLALE;
                else
-                       balloon3_ctl &= ~BALLOON3_NAND_CONTROL_FLALE;
-
-               __raw_writel(balloon3_ctl, BALLOON3_NAND_CONTROL_REG);
+                       balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLALE;
+
+               if (balloon3_ctl_clr)
+                       __raw_writel(balloon3_ctl_clr,
+                               BALLOON3_NAND_CONTROL_REG);
+               if (balloon3_ctl_set)
+                       __raw_writel(balloon3_ctl_set,
+                               BALLOON3_NAND_CONTROL_REG |
+                               BALLOON3_FPGA_SETnCLR);
        }
 
        if (cmd != NAND_CMD_NONE)
@@ -599,28 +601,33 @@ static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip)
        if (chip < 0 || chip > 3)
                return;
 
-       balloon3_ctl |= BALLOON3_NAND_CONTROL_FLCE0 |
-                       BALLOON3_NAND_CONTROL_FLCE1 |
-                       BALLOON3_NAND_CONTROL_FLCE2 |
-                       BALLOON3_NAND_CONTROL_FLCE3;
+       /* Assert all nCE lines */
+       __raw_writew(
+               BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
+               BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3,
+               BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
 
        /* Deassert correct nCE line */
-       balloon3_ctl &= ~(BALLOON3_NAND_CONTROL_FLCE0 << chip);
+       __raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
+               BALLOON3_NAND_CONTROL_REG);
+}
 
-       __raw_writew(balloon3_ctl, BALLOON3_NAND_CONTROL_REG);
+static int balloon3_nand_dev_ready(struct mtd_info *mtd)
+{
+       return __raw_readl(BALLOON3_NAND_STAT_REG) & BALLOON3_NAND_STAT_RNB;
 }
 
 static int balloon3_nand_probe(struct platform_device *pdev)
 {
-       void __iomem *temp_map;
        uint16_t ver;
        int ret;
 
-       __raw_writew(BALLOON3_NAND_CONTROL2_16BIT, BALLOON3_NAND_CONTROL2_REG);
+       __raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
+               BALLOON3_NAND_CONTROL2_REG | BALLOON3_FPGA_SETnCLR);
 
        ver = __raw_readw(BALLOON3_FPGA_VER);
-       if (ver > 0x0201)
-               pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. "
+       if (ver < 0x4f08)
+               pr_warn("The FPGA code, version 0x%04x, is too old. "
                        "NAND support might be broken in this version!", ver);
 
        /* Power up the NAND chips */
@@ -635,7 +642,11 @@ static int balloon3_nand_probe(struct platform_device *pdev)
        gpio_set_value(BALLOON3_GPIO_RUN_NAND, 1);
 
        /* Deassert all nCE lines and write protect line */
-       __raw_writel(balloon3_ctl, BALLOON3_NAND_CONTROL_REG);
+       __raw_writel(
+               BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
+               BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
+               BALLOON3_NAND_CONTROL_FLWP,
+               BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
        return 0;
 
 err2:
@@ -677,7 +688,7 @@ struct platform_nand_data balloon3_nand_pdata = {
        },
        .ctrl = {
                .hwcontrol      = 0,
-               .dev_ready      = 0,
+               .dev_ready      = balloon3_nand_dev_ready,
                .select_chip    = balloon3_nand_select_chip,
                .cmd_ctrl       = balloon3_nand_cmd_ctl,
                .probe          = balloon3_nand_probe,
@@ -802,7 +813,7 @@ static struct map_desc balloon3_io_desc[] __initdata = {
 
 static void __init balloon3_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
        iotable_init(balloon3_io_desc, ARRAY_SIZE(balloon3_io_desc));
 }
 
index 4bd7a3cda48c12b07932a36ffcaa473919f56224..4284513f396a041f7e94556f62a98319a833fc77 100644 (file)
@@ -149,7 +149,7 @@ static void __init capc7117_init(void)
 MACHINE_START(CAPC7117,
              "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
        .boot_params = 0xa0000100,
-       .map_io = pxa_map_io,
+       .map_io = pxa3xx_map_io,
        .init_irq = pxa3xx_init_irq,
        .timer = &pxa_timer,
        .init_machine = capc7117_init
diff --git a/arch/arm/mach-pxa/clock-pxa2xx.c b/arch/arm/mach-pxa/clock-pxa2xx.c
new file mode 100644 (file)
index 0000000..1ce0904
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * linux/arch/arm/mach-pxa/clock-pxa2xx.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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+
+#include <mach/pxa2xx-regs.h>
+
+#include "clock.h"
+
+void clk_pxa2xx_cken_enable(struct clk *clk)
+{
+       CKEN |= 1 << clk->cken;
+}
+
+void clk_pxa2xx_cken_disable(struct clk *clk)
+{
+       CKEN &= ~(1 << clk->cken);
+}
+
+const struct clkops clk_pxa2xx_cken_ops = {
+       .enable         = clk_pxa2xx_cken_enable,
+       .disable        = clk_pxa2xx_cken_disable,
+};
+
+#ifdef CONFIG_PM
+static uint32_t saved_cken;
+
+static int pxa2xx_clock_suspend(struct sys_device *d, pm_message_t state)
+{
+       saved_cken = CKEN;
+       return 0;
+}
+
+static int pxa2xx_clock_resume(struct sys_device *d)
+{
+       CKEN = saved_cken;
+       return 0;
+}
+#else
+#define pxa2xx_clock_suspend   NULL
+#define pxa2xx_clock_resume    NULL
+#endif
+
+struct sysdev_class pxa2xx_clock_sysclass = {
+       .name           = "pxa2xx-clock",
+       .suspend        = pxa2xx_clock_suspend,
+       .resume         = pxa2xx_clock_resume,
+};
+
+static int __init pxa2xx_clock_init(void)
+{
+       if (cpu_is_pxa2xx())
+               return sysdev_class_register(&pxa2xx_clock_sysclass);
+       return 0;
+}
+postcore_initcall(pxa2xx_clock_init);
diff --git a/arch/arm/mach-pxa/clock-pxa3xx.c b/arch/arm/mach-pxa/clock-pxa3xx.c
new file mode 100644 (file)
index 0000000..1b08a34
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * linux/arch/arm/mach-pxa/clock-pxa3xx.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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <mach/smemc.h>
+#include <mach/pxa3xx-regs.h>
+
+#include "clock.h"
+
+/* Crystal clock: 13MHz */
+#define BASE_CLK       13000000
+
+/* Ring Oscillator Clock: 60MHz */
+#define RO_CLK         60000000
+
+#define ACCR_D0CS      (1 << 26)
+#define ACCR_PCCE      (1 << 11)
+
+/* crystal frequency to HSIO bus frequency multiplier (HSS) */
+static unsigned char hss_mult[4] = { 8, 12, 16, 24 };
+
+/*
+ * Get the clock frequency as reflected by CCSR and the turbo flag.
+ * We assume these values have been applied via a fcs.
+ * If info is not 0 we also display the current settings.
+ */
+unsigned int pxa3xx_get_clk_frequency_khz(int info)
+{
+       unsigned long acsr, xclkcfg;
+       unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
+
+       /* Read XCLKCFG register turbo bit */
+       __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+       t = xclkcfg & 0x1;
+
+       acsr = ACSR;
+
+       xl  = acsr & 0x1f;
+       xn  = (acsr >> 8) & 0x7;
+       hss = (acsr >> 14) & 0x3;
+
+       XL = xl * BASE_CLK;
+       XN = xn * XL;
+
+       ro = acsr & ACCR_D0CS;
+
+       CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
+       HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
+
+       if (info) {
+               pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
+                       RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
+                       (ro) ? "" : "in");
+               pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
+                       XL / 1000000, (XL % 1000000) / 10000, xl);
+               pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
+                       XN / 1000000, (XN % 1000000) / 10000, xn,
+                       (t) ? "" : "in");
+               pr_info("HSIO bus clock: %d.%02dMHz\n",
+                       HSS / 1000000, (HSS % 1000000) / 10000);
+       }
+
+       return CLK / 1000;
+}
+
+/*
+ * Return the current AC97 clock frequency.
+ */
+static unsigned long clk_pxa3xx_ac97_getrate(struct clk *clk)
+{
+       unsigned long rate = 312000000;
+       unsigned long ac97_div;
+
+       ac97_div = AC97_DIV;
+
+       /* This may loose precision for some rates but won't for the
+        * standard 24.576MHz.
+        */
+       rate /= (ac97_div >> 12) & 0x7fff;
+       rate *= (ac97_div & 0xfff);
+
+       return rate;
+}
+
+/*
+ * Return the current HSIO bus clock frequency
+ */
+static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
+{
+       unsigned long acsr;
+       unsigned int hss, hsio_clk;
+
+       acsr = ACSR;
+
+       hss = (acsr >> 14) & 0x3;
+       hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
+
+       return hsio_clk;
+}
+
+/* crystal frequency to static memory controller multiplier (SMCFS) */
+static unsigned int smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
+static unsigned int df_clkdiv[4] = { 1, 2, 4, 1 };
+
+static unsigned long clk_pxa3xx_smemc_getrate(struct clk *clk)
+{
+       unsigned long acsr = ACSR;
+       unsigned long memclkcfg = __raw_readl(MEMCLKCFG);
+       unsigned int smcfs = (acsr >> 23) & 0x7;
+
+       return BASE_CLK * smcfs_mult[(acsr >> 23) & 0x7] /
+                       df_clkdiv[(memclkcfg >> 16) & 0x3];
+}
+
+void clk_pxa3xx_cken_enable(struct clk *clk)
+{
+       unsigned long mask = 1ul << (clk->cken & 0x1f);
+
+       if (clk->cken < 32)
+               CKENA |= mask;
+       else
+               CKENB |= mask;
+}
+
+void clk_pxa3xx_cken_disable(struct clk *clk)
+{
+       unsigned long mask = 1ul << (clk->cken & 0x1f);
+
+       if (clk->cken < 32)
+               CKENA &= ~mask;
+       else
+               CKENB &= ~mask;
+}
+
+const struct clkops clk_pxa3xx_cken_ops = {
+       .enable         = clk_pxa3xx_cken_enable,
+       .disable        = clk_pxa3xx_cken_disable,
+};
+
+const struct clkops clk_pxa3xx_hsio_ops = {
+       .enable         = clk_pxa3xx_cken_enable,
+       .disable        = clk_pxa3xx_cken_disable,
+       .getrate        = clk_pxa3xx_hsio_getrate,
+};
+
+const struct clkops clk_pxa3xx_ac97_ops = {
+       .enable         = clk_pxa3xx_cken_enable,
+       .disable        = clk_pxa3xx_cken_disable,
+       .getrate        = clk_pxa3xx_ac97_getrate,
+};
+
+const struct clkops clk_pxa3xx_smemc_ops = {
+       .enable         = clk_pxa3xx_cken_enable,
+       .disable        = clk_pxa3xx_cken_disable,
+       .getrate        = clk_pxa3xx_smemc_getrate,
+};
+
+static void clk_pout_enable(struct clk *clk)
+{
+       OSCC |= OSCC_PEN;
+}
+
+static void clk_pout_disable(struct clk *clk)
+{
+       OSCC &= ~OSCC_PEN;
+}
+
+const struct clkops clk_pxa3xx_pout_ops = {
+       .enable         = clk_pout_enable,
+       .disable        = clk_pout_disable,
+};
+
+#ifdef CONFIG_PM
+static uint32_t cken[2];
+static uint32_t accr;
+
+static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state)
+{
+       cken[0] = CKENA;
+       cken[1] = CKENB;
+       accr = ACCR;
+       return 0;
+}
+
+static int pxa3xx_clock_resume(struct sys_device *d)
+{
+       ACCR = accr;
+       CKENA = cken[0];
+       CKENB = cken[1];
+       return 0;
+}
+#else
+#define pxa3xx_clock_suspend   NULL
+#define pxa3xx_clock_resume    NULL
+#endif
+
+struct sysdev_class pxa3xx_clock_sysclass = {
+       .name           = "pxa3xx-clock",
+       .suspend        = pxa3xx_clock_suspend,
+       .resume         = pxa3xx_clock_resume,
+};
+
+static int __init pxa3xx_clock_init(void)
+{
+       if (cpu_is_pxa3xx() || cpu_is_pxa95x())
+               return sysdev_class_register(&pxa3xx_clock_sysclass);
+       return 0;
+}
+postcore_initcall(pxa3xx_clock_init);
index abba0089a2ae0d6af3ca35a9bf961d9a5a65406e..8184fe2d71c34c55c9d783645424c5073ce66d31 100644 (file)
@@ -3,21 +3,12 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
-#include <linux/platform_device.h>
 #include <linux/delay.h>
 
 #include <asm/clkdev.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/hardware.h>
 
-#include "devices.h"
-#include "generic.h"
 #include "clock.h"
 
 static DEFINE_SPINLOCK(clocks_lock);
@@ -63,18 +54,19 @@ unsigned long clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
-
-void clk_cken_enable(struct clk *clk)
+void clk_dummy_enable(struct clk *clk)
 {
-       CKEN |= 1 << clk->cken;
 }
 
-void clk_cken_disable(struct clk *clk)
+void clk_dummy_disable(struct clk *clk)
 {
-       CKEN &= ~(1 << clk->cken);
 }
 
-const struct clkops clk_cken_ops = {
-       .enable         = clk_cken_enable,
-       .disable        = clk_cken_disable,
+const struct clkops clk_dummy_ops = {
+       .enable         = clk_dummy_enable,
+       .disable        = clk_dummy_disable,
+};
+
+struct clk clk_dummy = {
+       .ops            = &clk_dummy_ops,
 };
index d8488742b8075179fd4d66026d79730e00505a21..6e949944f2ec97233dfe0c74e4fd34ff22ad928c 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/sysdev.h>
 #include <asm/clkdev.h>
 
 struct clkops {
@@ -14,6 +15,12 @@ struct clk {
        unsigned int            enabled;
 };
 
+void clk_dummy_enable(struct clk *);
+void clk_dummy_disable(struct clk *);
+
+extern const struct clkops clk_dummy_ops;
+extern struct clk clk_dummy;
+
 #define INIT_CLKREG(_clk,_devname,_conname)            \
        {                                               \
                .clk            = _clk,                 \
@@ -21,14 +28,6 @@ struct clk {
                .con_id         = _conname,             \
        }
 
-#define DEFINE_CKEN(_name, _cken, _rate, _delay)       \
-struct clk clk_##_name = {                             \
-               .ops    = &clk_cken_ops,                \
-               .rate   = _rate,                        \
-               .cken   = CKEN_##_cken,                 \
-               .delay  = _delay,                       \
-       }
-
 #define DEFINE_CK(_name, _cken, _ops)                  \
 struct clk clk_##_name = {                             \
                .ops    = _ops,                         \
@@ -42,28 +41,38 @@ struct clk clk_##_name = {                          \
                .delay  = _delay,                       \
        }
 
-extern const struct clkops clk_cken_ops;
-
-void clk_cken_enable(struct clk *clk);
-void clk_cken_disable(struct clk *clk);
-
-#ifdef CONFIG_PXA3xx
-#define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay)  \
+#define DEFINE_PXA2_CKEN(_name, _cken, _rate, _delay)  \
 struct clk clk_##_name = {                             \
-               .ops    = &clk_pxa3xx_cken_ops,         \
+               .ops    = &clk_pxa2xx_cken_ops,         \
                .rate   = _rate,                        \
                .cken   = CKEN_##_cken,                 \
                .delay  = _delay,                       \
        }
 
-#define DEFINE_PXA3_CK(_name, _cken, _ops)             \
+extern const struct clkops clk_pxa2xx_cken_ops;
+
+void clk_pxa2xx_cken_enable(struct clk *clk);
+void clk_pxa2xx_cken_disable(struct clk *clk);
+
+extern struct sysdev_class pxa2xx_clock_sysclass;
+
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+#define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay)  \
 struct clk clk_##_name = {                             \
-               .ops    = _ops,                         \
+               .ops    = &clk_pxa3xx_cken_ops,         \
+               .rate   = _rate,                        \
                .cken   = CKEN_##_cken,                 \
+               .delay  = _delay,                       \
        }
 
 extern const struct clkops clk_pxa3xx_cken_ops;
+extern const struct clkops clk_pxa3xx_hsio_ops;
+extern const struct clkops clk_pxa3xx_ac97_ops;
+extern const struct clkops clk_pxa3xx_pout_ops;
+extern const struct clkops clk_pxa3xx_smemc_ops;
+
 extern void clk_pxa3xx_cken_enable(struct clk *);
 extern void clk_pxa3xx_cken_disable(struct clk *);
-#endif
 
+extern struct sysdev_class pxa3xx_clock_sysclass;
+#endif
index d34b99febeb99c76eef86caf2b20881f45b39fc1..b734d8468168a611b3ff16a9645686dab07dbe6d 100644 (file)
@@ -24,6 +24,7 @@
 #include <mach/pxa2xx-regs.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
+#include <mach/smemc.h>
 
 #include <asm/hardware/it8152.h>
 
@@ -392,9 +393,9 @@ static int cmx2xx_suspend(struct sys_device *dev, pm_message_t state)
        cmx2xx_pci_suspend();
 
        /* save MSC registers */
-       sleep_save_msc[0] = MSC0;
-       sleep_save_msc[1] = MSC1;
-       sleep_save_msc[2] = MSC2;
+       sleep_save_msc[0] = __raw_readl(MSC0);
+       sleep_save_msc[1] = __raw_readl(MSC1);
+       sleep_save_msc[2] = __raw_readl(MSC2);
 
        /* setup power saving mode registers */
        PCFR = 0x0;
@@ -416,9 +417,9 @@ static int cmx2xx_resume(struct sys_device *dev)
        cmx2xx_pci_resume();
 
        /* restore MSC registers */
-       MSC0 = sleep_save_msc[0];
-       MSC1 = sleep_save_msc[1];
-       MSC2 = sleep_save_msc[2];
+       __raw_writel(sleep_save_msc[0], MSC0);
+       __raw_writel(sleep_save_msc[1], MSC1);
+       __raw_writel(sleep_save_msc[2], MSC2);
 
        return 0;
 }
@@ -498,7 +499,12 @@ static struct map_desc cmx2xx_io_desc[] __initdata = {
 
 static void __init cmx2xx_map_io(void)
 {
-       pxa_map_io();
+       if (cpu_is_pxa25x())
+               pxa25x_map_io();
+
+       if (cpu_is_pxa27x())
+               pxa27x_map_io();
+
        iotable_init(cmx2xx_io_desc, ARRAY_SIZE(cmx2xx_io_desc));
 
        it8152_base_address = CMX2XX_IT8152_VIRT;
@@ -506,7 +512,11 @@ static void __init cmx2xx_map_io(void)
 #else
 static void __init cmx2xx_map_io(void)
 {
-       pxa_map_io();
+       if (cpu_is_pxa25x())
+               pxa25x_map_io();
+
+       if (cpu_is_pxa27x())
+               pxa27x_map_io();
 }
 #endif
 
index 922b1075b9de75ea38d2070cbedaf4f0a16a5d2b..7984268508b65cf2486330fd5e1c78efcfb57530 100644 (file)
@@ -857,7 +857,7 @@ static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
 
 MACHINE_START(CM_X300, "CM-X300 module")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = cm_x300_init,
similarity index 51%
rename from arch/arm/mach-pxa/colibri-pxa270-evalboard.c
rename to arch/arm/mach-pxa/colibri-evalboard.c
index 0f3b632c3b14f52ad182597198088040420f79c5..6b2c800a1133fd466c9c138b18a64d7956790023 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  linux/arch/arm/mach-pxa/colibri-pxa270-evalboard.c
+ *  linux/arch/arm/mach-pxa/colibri-evalboard.c
  *
- *  Support for Toradex PXA270 based Colibri Evaluation Carrier Board
+ *  Support for Toradex Colibri Evaluation Carrier Board
  *  Daniel Mack <daniel@caiaq.de>
  *  Marek Vasut <marek.vasut@gmail.com>
  *
@@ -19,6 +19,7 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/mach/arch.h>
+#include <linux/i2c.h>
 
 #include <mach/pxa27x.h>
 #include <mach/colibri.h>
 #include <mach/ohci.h>
 #include <mach/pxa27x-udc.h>
 
+#include <plat/i2c.h>
+
 #include "generic.h"
 #include "devices.h"
 
-/******************************************************************************
- * Pin configuration
- ******************************************************************************/
-static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {
-       /* MMC */
-       GPIO32_MMC_CLK,
-       GPIO92_MMC_DAT_0,
-       GPIO109_MMC_DAT_1,
-       GPIO110_MMC_DAT_2,
-       GPIO111_MMC_DAT_3,
-       GPIO112_MMC_CMD,
-       GPIO0_GPIO,     /* SD detect */
-
-       /* FFUART */
-       GPIO39_FFUART_TXD,
-       GPIO34_FFUART_RXD,
-
-       /* UHC */
-       GPIO88_USBH1_PWR,
-       GPIO89_USBH1_PEN,
-       GPIO119_USBH2_PWR,
-       GPIO120_USBH2_PEN,
-};
-
 /******************************************************************************
  * SD/MMC card controller
  ******************************************************************************/
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
-static struct pxamci_platform_data colibri_pxa270_mci_platform_data = {
+static struct pxamci_platform_data colibri_mci_platform_data = {
        .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
        .gpio_power             = -1,
-       .gpio_card_detect       = GPIO0_COLIBRI_PXA270_SD_DETECT,
        .gpio_card_ro           = -1,
        .detect_delay_ms        = 200,
 };
 
-static void __init colibri_pxa270_mmc_init(void)
+static void __init colibri_mmc_init(void)
 {
-       pxa_set_mci_info(&colibri_pxa270_mci_platform_data);
+       if (machine_is_colibri())       /* PXA270 Colibri */
+               colibri_mci_platform_data.gpio_card_detect =
+                       GPIO0_COLIBRI_PXA270_SD_DETECT;
+       if (machine_is_colibri300())    /* PXA300 Colibri */
+               colibri_mci_platform_data.gpio_card_detect =
+                       GPIO39_COLIBRI_PXA300_SD_DETECT;
+       else                            /* PXA320 Colibri */
+               colibri_mci_platform_data.gpio_card_detect =
+                       GPIO28_COLIBRI_PXA320_SD_DETECT;
+
+       pxa_set_mci_info(&colibri_mci_platform_data);
 }
 #else
-static inline void colibri_pxa270_mmc_init(void) {}
+static inline void colibri_mmc_init(void) {}
 #endif
 
 /******************************************************************************
  * USB Host
  ******************************************************************************/
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static int colibri_pxa270_ohci_init(struct device *dev)
+static int colibri_ohci_init(struct device *dev)
 {
        UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
        return 0;
 }
 
-static struct pxaohci_platform_data colibri_pxa270_ohci_info = {
+static struct pxaohci_platform_data colibri_ohci_info = {
        .port_mode      = PMM_PERPORT_MODE,
-       .flags          = ENABLE_PORT1 | ENABLE_PORT2 |
+       .flags          = ENABLE_PORT1 |
                          POWER_CONTROL_LOW | POWER_SENSE_LOW,
-       .init           = colibri_pxa270_ohci_init,
+       .init           = colibri_ohci_init,
 };
 
-static void __init colibri_pxa270_uhc_init(void)
+static void __init colibri_uhc_init(void)
 {
-       pxa_set_ohci_info(&colibri_pxa270_ohci_info);
+       /* Colibri PXA270 has two usb ports, TBA for 320 */
+       if (machine_is_colibri())
+               colibri_ohci_info.flags |= ENABLE_PORT2;
+
+       pxa_set_ohci_info(&colibri_ohci_info);
 }
 #else
-static inline void colibri_pxa270_uhc_init(void) {}
+static inline void colibri_uhc_init(void) {}
 #endif
 
-void __init colibri_pxa270_evalboard_init(void)
+/******************************************************************************
+ * I2C RTC
+ ******************************************************************************/
+#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE)
+static struct i2c_board_info __initdata colibri_i2c_devs[] = {
+       {
+               I2C_BOARD_INFO("m41t00", 0x68),
+       },
+};
+
+static void __init colibri_rtc_init(void)
+{
+       pxa_set_i2c_info(NULL);
+       i2c_register_board_info(0, ARRAY_AND_SIZE(colibri_i2c_devs));
+}
+#else
+static inline void colibri_rtc_init(void) {}
+#endif
+
+void __init colibri_evalboard_init(void)
 {
-       pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa270_evalboard_pin_config));
        pxa_set_ffuart_info(NULL);
        pxa_set_btuart_info(NULL);
        pxa_set_stuart_info(NULL);
 
-       colibri_pxa270_mmc_init();
-       colibri_pxa270_uhc_init();
+       colibri_mmc_init();
+       colibri_uhc_init();
+       colibri_rtc_init();
 }
-
index 37f0f3ed7c612d87b8974609da07bcfb4511c4e6..07b62a096f1757f3f4d8e44220e264074494606c 100644 (file)
 #define GPIO55_INCOME_LED_B     (55)
 #define GPIO113_INCOME_TS_IRQ   (113)
 
-/******************************************************************************
- * Pin configuration
- ******************************************************************************/
-static mfp_cfg_t income_pin_config[] __initdata = {
-       /* MMC */
-       GPIO32_MMC_CLK,
-       GPIO92_MMC_DAT_0,
-       GPIO109_MMC_DAT_1,
-       GPIO110_MMC_DAT_2,
-       GPIO111_MMC_DAT_3,
-       GPIO112_MMC_CMD,
-       GPIO0_GPIO,     /* SD detect */
-       GPIO1_GPIO,     /* SD read-only */
-
-       /* FFUART */
-       GPIO39_FFUART_TXD,
-       GPIO34_FFUART_RXD,
-
-       /* BFUART */
-       GPIO42_BTUART_RXD,
-       GPIO43_BTUART_TXD,
-       GPIO45_BTUART_RTS,
-
-       /* STUART */
-       GPIO46_STUART_RXD,
-       GPIO47_STUART_TXD,
-
-       /* UHC */
-       GPIO88_USBH1_PWR,
-       GPIO89_USBH1_PEN,
-
-       /* LCD */
-       GPIOxx_LCD_TFT_16BPP,
-
-       /* PWM */
-       GPIO16_PWM0_OUT,
-
-       /* I2C */
-       GPIO117_I2C_SCL,
-       GPIO118_I2C_SDA,
-
-       /* LED */
-       GPIO54_GPIO,    /* LED A */
-       GPIO55_GPIO,    /* LED B */
-};
-
 /******************************************************************************
  * SD/MMC card controller
  ******************************************************************************/
@@ -257,7 +211,6 @@ static inline void income_pwm_init(void) {}
 
 void __init colibri_pxa270_income_boardinit(void)
 {
-       pxa2xx_mfp_config(ARRAY_AND_SIZE(income_pin_config));
        pxa_set_ffuart_info(NULL);
        pxa_set_btuart_info(NULL);
        pxa_set_stuart_info(NULL);
index bc045100ec159927cdcd1afe84b954c103537742..6fc5d328ba7f80b2a40fb1926691fdcfced0d7f8 100644 (file)
 #include "devices.h"
 #include "generic.h"
 
+/******************************************************************************
+ * Evaluation board MFP
+ ******************************************************************************/
+#ifdef  CONFIG_MACH_COLIBRI_EVALBOARD
+static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {
+       /* MMC */
+       GPIO32_MMC_CLK,
+       GPIO92_MMC_DAT_0,
+       GPIO109_MMC_DAT_1,
+       GPIO110_MMC_DAT_2,
+       GPIO111_MMC_DAT_3,
+       GPIO112_MMC_CMD,
+       GPIO0_GPIO,     /* SD detect */
+
+       /* FFUART */
+       GPIO39_FFUART_TXD,
+       GPIO34_FFUART_RXD,
+
+       /* UHC */
+       GPIO88_USBH1_PWR,
+       GPIO89_USBH1_PEN,
+       GPIO119_USBH2_PWR,
+       GPIO120_USBH2_PEN,
+
+       /* PCMCIA */
+       GPIO85_nPCE_1,
+       GPIO54_nPCE_2,
+       GPIO55_nPREG,
+       GPIO50_nPIOR,
+       GPIO51_nPIOW,
+       GPIO49_nPWE,
+       GPIO48_nPOE,
+       GPIO57_nIOIS16,
+       GPIO56_nPWAIT,
+       GPIO104_PSKTSEL,
+       GPIO53_GPIO,    /* RESET */
+       GPIO83_GPIO,    /* BVD1 */
+       GPIO82_GPIO,    /* BVD2 */
+       GPIO1_GPIO,     /* READY */
+       GPIO84_GPIO,    /* DETECT */
+       GPIO107_GPIO,   /* PPEN */
+
+       /* I2C */
+       GPIO117_I2C_SCL,
+       GPIO118_I2C_SDA,
+};
+#else
+static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {};
+#endif
+
+#ifdef CONFIG_MACH_COLIBRI_PXA270_INCOME
+static mfp_cfg_t income_pin_config[] __initdata = {
+       /* MMC */
+       GPIO32_MMC_CLK,
+       GPIO92_MMC_DAT_0,
+       GPIO109_MMC_DAT_1,
+       GPIO110_MMC_DAT_2,
+       GPIO111_MMC_DAT_3,
+       GPIO112_MMC_CMD,
+       GPIO0_GPIO,     /* SD detect */
+       GPIO1_GPIO,     /* SD read-only */
+
+       /* FFUART */
+       GPIO39_FFUART_TXD,
+       GPIO34_FFUART_RXD,
+
+       /* BFUART */
+       GPIO42_BTUART_RXD,
+       GPIO43_BTUART_TXD,
+       GPIO45_BTUART_RTS,
+
+       /* STUART */
+       GPIO46_STUART_RXD,
+       GPIO47_STUART_TXD,
+
+       /* UHC */
+       GPIO88_USBH1_PWR,
+       GPIO89_USBH1_PEN,
+
+       /* LCD */
+       GPIOxx_LCD_TFT_16BPP,
+
+       /* PWM */
+       GPIO16_PWM0_OUT,
+
+       /* I2C */
+       GPIO117_I2C_SCL,
+       GPIO118_I2C_SDA,
+
+       /* LED */
+       GPIO54_GPIO,    /* LED A */
+       GPIO55_GPIO,    /* LED B */
+};
+#else
+static mfp_cfg_t income_pin_config[] __initdata = {};
+#endif
+
 /******************************************************************************
  * Pin configuration
  ******************************************************************************/
@@ -184,10 +281,13 @@ static void __init colibri_pxa270_init(void)
        colibri_pxa270_tsc_init();
 
        switch (colibri_pxa270_baseboard) {
-       case COLIBRI_PXA270_EVALBOARD:
-               colibri_pxa270_evalboard_init();
+       case COLIBRI_EVALBOARD:
+               pxa2xx_mfp_config(ARRAY_AND_SIZE(
+                       colibri_pxa270_evalboard_pin_config));
+               colibri_evalboard_init();
                break;
        case COLIBRI_PXA270_INCOME:
+               pxa2xx_mfp_config(ARRAY_AND_SIZE(income_pin_config));
                colibri_pxa270_income_boardinit();
                break;
        default:
@@ -209,7 +309,7 @@ static void __init colibri_pxa270_income_init(void)
 MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
        .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
        .init_machine   = colibri_pxa270_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -217,7 +317,7 @@ MACHINE_END
 MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
        .boot_params    = 0xa0000100,
        .init_machine   = colibri_pxa270_income_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
index a70b256591e673414f0499c3bbe6a0b9e64b923e..fddb16d07eb03da5e8574edccd579b17db5a17b8 100644 (file)
 #include "generic.h"
 #include "devices.h"
 
+
+#ifdef CONFIG_MACH_COLIBRI_EVALBOARD
+static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = {
+       /* MMC */
+       GPIO7_MMC1_CLK,
+       GPIO14_MMC1_CMD,
+       GPIO3_MMC1_DAT0,
+       GPIO4_MMC1_DAT1,
+       GPIO5_MMC1_DAT2,
+       GPIO6_MMC1_DAT3,
+       GPIO39_GPIO,    /* SD detect */
+
+       /* UHC */
+       GPIO0_2_USBH_PEN,
+       GPIO1_2_USBH_PWR,
+       GPIO77_USB_P3_1,
+       GPIO78_USB_P3_2,
+       GPIO79_USB_P3_3,
+       GPIO80_USB_P3_4,
+       GPIO81_USB_P3_5,
+       GPIO82_USB_P3_6,
+
+       /* I2C */
+       GPIO21_I2C_SCL,
+       GPIO22_I2C_SDA,
+};
+#else
+static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = {};
+#endif
+
 #if defined(CONFIG_AX88796)
 #define COLIBRI_ETH_IRQ_GPIO   mfp_to_gpio(GPIO26_GPIO)
-
 /*
  * Asix AX88796 Ethernet
  */
@@ -80,35 +109,6 @@ static void __init colibri_pxa300_init_eth(void)
 static inline void __init colibri_pxa300_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static mfp_cfg_t colibri_pxa300_usb_pin_config[] __initdata = {
-       GPIO0_2_USBH_PEN,
-       GPIO1_2_USBH_PWR,
-};
-
-static struct pxaohci_platform_data colibri_pxa300_ohci_info = {
-       .port_mode      = PMM_GLOBAL_MODE,
-       .flags          = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
-};
-
-void __init colibri_pxa300_init_ohci(void)
-{
-       pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_usb_pin_config));
-       pxa_set_ohci_info(&colibri_pxa300_ohci_info);
-}
-#else
-static inline void colibri_pxa300_init_ohci(void) {}
-#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */
-
-static mfp_cfg_t colibri_pxa300_mmc_pin_config[] __initdata = {
-       GPIO7_MMC1_CLK,
-       GPIO14_MMC1_CMD,
-       GPIO3_MMC1_DAT0,
-       GPIO4_MMC1_DAT1,
-       GPIO5_MMC1_DAT2,
-       GPIO6_MMC1_DAT3,
-};
-
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static mfp_cfg_t colibri_pxa300_lcd_pin_config[] __initdata = {
        GPIO54_LCD_LDD_0,
@@ -171,24 +171,21 @@ static inline void colibri_pxa310_init_ac97(void) {}
 
 void __init colibri_pxa300_init(void)
 {
-       pxa_set_ffuart_info(NULL);
-       pxa_set_btuart_info(NULL);
-       pxa_set_stuart_info(NULL);
-
        colibri_pxa300_init_eth();
-       colibri_pxa300_init_ohci();
        colibri_pxa3xx_init_nand();
        colibri_pxa300_init_lcd();
        colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO));
        colibri_pxa310_init_ac97();
-       colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa300_mmc_pin_config),
-                               mfp_to_gpio(MFP_PIN_GPIO13));
+
+       /* Evalboard init */
+       pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_evalboard_pin_config));
+       colibri_evalboard_init();
 }
 
 MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
        .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
        .init_machine   = colibri_pxa300_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
index ca5f29e2e9cd412fcb3ca010603ffd3019898190..ff9ff5f4fc47e599f409c10935151e65621023e1 100644 (file)
 #include "generic.h"
 #include "devices.h"
 
+#ifdef CONFIG_MACH_COLIBRI_EVALBOARD
+static mfp_cfg_t colibri_pxa320_evalboard_pin_config[] __initdata = {
+       /* MMC */
+       GPIO22_MMC1_CLK,
+       GPIO23_MMC1_CMD,
+       GPIO18_MMC1_DAT0,
+       GPIO19_MMC1_DAT1,
+       GPIO20_MMC1_DAT2,
+       GPIO21_MMC1_DAT3,
+       GPIO28_GPIO,    /* SD detect */
+
+       /* UART 1 configuration (may be set by bootloader) */
+       GPIO99_UART1_CTS,
+       GPIO104_UART1_RTS,
+       GPIO97_UART1_RXD,
+       GPIO98_UART1_TXD,
+       GPIO101_UART1_DTR,
+       GPIO103_UART1_DSR,
+       GPIO100_UART1_DCD,
+       GPIO102_UART1_RI,
+
+       /* UART 2 configuration */
+       GPIO109_UART2_CTS,
+       GPIO112_UART2_RTS,
+       GPIO110_UART2_RXD,
+       GPIO111_UART2_TXD,
+
+       /* UART 3 configuration */
+       GPIO30_UART3_RXD,
+       GPIO31_UART3_TXD,
+
+       /* UHC */
+       GPIO2_2_USBH_PEN,
+       GPIO3_2_USBH_PWR,
+
+       /* I2C */
+       GPIO32_I2C_SCL,
+       GPIO33_I2C_SDA,
+
+       /* PCMCIA */
+       MFP_CFG(GPIO59, AF7),   /* PRST ; AF7 to tristate */
+       MFP_CFG(GPIO61, AF7),   /* PCE1 ; AF7 to tristate */
+       MFP_CFG(GPIO60, AF7),   /* PCE2 ; AF7 to tristate */
+       MFP_CFG(GPIO62, AF7),   /* PCD ; AF7 to tristate */
+       MFP_CFG(GPIO56, AF7),   /* PSKTSEL ; AF7 to tristate */
+       GPIO27_GPIO,            /* RDnWR ; input/tristate */
+       GPIO50_GPIO,            /* PREG ; input/tristate */
+       GPIO2_RDY,
+       GPIO5_NPIOR,
+       GPIO6_NPIOW,
+       GPIO7_NPIOS16,
+       GPIO8_NPWAIT,
+       GPIO29_GPIO,            /* PRDY (READY GPIO) */
+       GPIO57_GPIO,            /* PPEN (POWER GPIO) */
+       GPIO81_GPIO,            /* PCD (DETECT GPIO) */
+       GPIO77_GPIO,            /* PRST (RESET GPIO) */
+       GPIO53_GPIO,            /* PBVD1 */
+       GPIO79_GPIO,            /* PBVD2 */
+       GPIO54_GPIO,            /* POE */
+};
+#else
+static mfp_cfg_t colibri_pxa320_evalboard_pin_config[] __initdata = {};
+#endif
+
 #if defined(CONFIG_AX88796)
 #define COLIBRI_ETH_IRQ_GPIO   mfp_to_gpio(GPIO36_GPIO)
-
 /*
  * Asix AX88796 Ethernet
  */
@@ -84,26 +147,6 @@ static void __init colibri_pxa320_init_eth(void)
 static inline void __init colibri_pxa320_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static mfp_cfg_t colibri_pxa320_usb_pin_config[] __initdata = {
-       GPIO2_2_USBH_PEN,
-       GPIO3_2_USBH_PWR,
-};
-
-static struct pxaohci_platform_data colibri_pxa320_ohci_info = {
-       .port_mode      = PMM_GLOBAL_MODE,
-       .flags          = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
-};
-
-void __init colibri_pxa320_init_ohci(void)
-{
-       pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_usb_pin_config));
-       pxa_set_ohci_info(&colibri_pxa320_ohci_info);
-}
-#else
-static inline void colibri_pxa320_init_ohci(void) {}
-#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */
-
 #if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
 static struct gpio_vbus_mach_info colibri_pxa320_gpio_vbus_info = {
        .gpio_vbus              = mfp_to_gpio(MFP_PIN_GPIO96),
@@ -140,15 +183,6 @@ static void __init colibri_pxa320_init_udc(void)
 static inline void colibri_pxa320_init_udc(void) {}
 #endif
 
-static mfp_cfg_t colibri_pxa320_mmc_pin_config[] __initdata = {
-       GPIO22_MMC1_CLK,
-       GPIO23_MMC1_CMD,
-       GPIO18_MMC1_DAT0,
-       GPIO19_MMC1_DAT1,
-       GPIO20_MMC1_DAT2,
-       GPIO21_MMC1_DAT3
-};
-
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static mfp_cfg_t colibri_pxa320_lcd_pin_config[] __initdata = {
        GPIO6_2_LCD_LDD_0,
@@ -205,59 +239,24 @@ static inline void __init colibri_pxa320_init_ac97(void)
 static inline void colibri_pxa320_init_ac97(void) {}
 #endif
 
-/*
- * The following configuration is verified to work with the Toradex Orchid
- * carrier board
- */
-static mfp_cfg_t colibri_pxa320_uart_pin_config[] __initdata = {
-       /* UART 1 configuration (may be set by bootloader) */
-       GPIO99_UART1_CTS,
-       GPIO104_UART1_RTS,
-       GPIO97_UART1_RXD,
-       GPIO98_UART1_TXD,
-       GPIO101_UART1_DTR,
-       GPIO103_UART1_DSR,
-       GPIO100_UART1_DCD,
-       GPIO102_UART1_RI,
-
-       /* UART 2 configuration */
-       GPIO109_UART2_CTS,
-       GPIO112_UART2_RTS,
-       GPIO110_UART2_RXD,
-       GPIO111_UART2_TXD,
-
-       /* UART 3 configuration */
-       GPIO30_UART3_RXD,
-       GPIO31_UART3_TXD,
-};
-
-static void __init colibri_pxa320_init_uart(void)
-{
-       pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_uart_pin_config));
-}
-
 void __init colibri_pxa320_init(void)
 {
-       pxa_set_ffuart_info(NULL);
-       pxa_set_btuart_info(NULL);
-       pxa_set_stuart_info(NULL);
-
        colibri_pxa320_init_eth();
-       colibri_pxa320_init_ohci();
        colibri_pxa3xx_init_nand();
        colibri_pxa320_init_lcd();
        colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO));
        colibri_pxa320_init_ac97();
-       colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa320_mmc_pin_config),
-                               mfp_to_gpio(MFP_PIN_GPIO28));
-       colibri_pxa320_init_uart();
        colibri_pxa320_init_udc();
+
+       /* Evalboard init */
+       pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_evalboard_pin_config));
+       colibri_evalboard_init();
 }
 
 MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
        .boot_params    = COLIBRI_SDRAM_BASE + 0x100,
        .init_machine   = colibri_pxa320_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
index 199afa2ae30315e48f0c54cbdbdf8e658a880aca..96b2d9fbfef0b8e6fda574cd76842b7303dbecb3 100644 (file)
@@ -64,55 +64,6 @@ void __init colibri_pxa3xx_init_eth(struct ax_plat_data *plat_data)
 }
 #endif
 
-#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
-static int mmc_detect_pin;
-
-static int colibri_pxa3xx_mci_init(struct device *dev,
-                                  irq_handler_t colibri_mmc_detect_int,
-                                  void *data)
-{
-       int ret;
-
-       ret = gpio_request(mmc_detect_pin, "mmc card detect");
-       if (ret)
-               return ret;
-
-       gpio_direction_input(mmc_detect_pin);
-       ret = request_irq(gpio_to_irq(mmc_detect_pin), colibri_mmc_detect_int,
-                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                         "MMC card detect", data);
-       if (ret) {
-               gpio_free(mmc_detect_pin);
-               return ret;
-       }
-
-       return 0;
-}
-
-static void colibri_pxa3xx_mci_exit(struct device *dev, void *data)
-{
-       free_irq(mmc_detect_pin, data);
-       gpio_free(gpio_to_irq(mmc_detect_pin));
-}
-
-static struct pxamci_platform_data colibri_pxa3xx_mci_platform_data = {
-       .detect_delay_ms        = 200,
-       .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
-       .init                   = colibri_pxa3xx_mci_init,
-       .exit                   = colibri_pxa3xx_mci_exit,
-       .gpio_card_detect       = -1,
-       .gpio_card_ro           = -1,
-       .gpio_power             = -1,
-};
-
-void __init colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin)
-{
-       pxa3xx_mfp_config(pins, len);
-       mmc_detect_pin = detect_pin;
-       pxa_set_mci_info(&colibri_pxa3xx_mci_platform_data);
-}
-#endif /* CONFIG_MMC_PXA || CONFIG_MMC_PXA_MODULE */
-
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static int lcd_bl_pin;
 
index 821229acabe6333ff3787b14ac9e8892c1c6811c..9f3e5af0a0db342170ee957ed23bf7a4609a3461 100644 (file)
@@ -721,7 +721,7 @@ static void __init fixup_corgi(struct machine_desc *desc,
 #ifdef CONFIG_MACH_CORGI
 MACHINE_START(CORGI, "SHARP Corgi")
        .fixup          = fixup_corgi,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
@@ -731,7 +731,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_SHEPHERD
 MACHINE_START(SHEPHERD, "SHARP Shepherd")
        .fixup          = fixup_corgi,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
@@ -741,7 +741,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_HUSKY
 MACHINE_START(HUSKY, "SHARP Husky")
        .fixup          = fixup_corgi,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .init_machine   = corgi_init,
        .timer          = &pxa_timer,
index 58093d9e07be44ea482df319c88acb78c0db3975..6a7aeab42f6ca27b03d7f6b1b95251550a62554d 100644 (file)
 #include <linux/cpufreq.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
+#include <linux/io.h>
 
 #include <mach/pxa2xx-regs.h>
+#include <mach/smemc.h>
 
 #ifdef DEBUG
 static unsigned int freq_debug;
@@ -242,7 +244,7 @@ static void pxa27x_guess_max_freq(void)
 
 static void init_sdram_rows(void)
 {
-       uint32_t mdcnfg = MDCNFG;
+       uint32_t mdcnfg = __raw_readl(MDCNFG);
        unsigned int drac2 = 0, drac0 = 0;
 
        if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
@@ -331,8 +333,8 @@ static int pxa_set_target(struct cpufreq_policy *policy,
         * we need to preset the smaller DRI before the change.  If we're
         * speeding up we need to set the larger DRI value after the change.
         */
-       preset_mdrefr = postset_mdrefr = MDREFR;
-       if ((MDREFR & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) {
+       preset_mdrefr = postset_mdrefr = __raw_readl(MDREFR);
+       if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) {
                preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK);
                preset_mdrefr |= mdrefr_dri(new_freq_mem);
        }
@@ -370,7 +372,7 @@ static int pxa_set_target(struct cpufreq_policy *policy,
 3:             nop                                                     \n\
          "
                     : "=&r" (unused)
-                    : "r" (&MDREFR), "r" (cclkcfg),
+                    : "r" (MDREFR), "r" (cclkcfg),
                       "r" (preset_mdrefr), "r" (postset_mdrefr)
                     : "r4", "r5");
        local_irq_restore(flags);
index 57cacaff194db96ea3f83590517e9339efd6002e..a305424a967ddb5c67f4debd20d425d458661029 100644 (file)
@@ -27,6 +27,7 @@
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/audio.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -255,9 +256,9 @@ static struct platform_device *devices[] __initdata = {
 static void __init csb726_init(void)
 {
        pxa2xx_mfp_config(ARRAY_AND_SIZE(csb726_pin_config));
-/*     MSC1 = 0x7ffc3ffc; *//* LAN9215/EXP_CS */
-/*     MSC2 = 0x06697ff4; *//* none/SM501 */
-       MSC2 = (MSC2 & ~0xffff) | 0x7ff4; /* SM501 */
+/*     __raw_writel(0x7ffc3ffc, MSC1); *//* LAN9215/EXP_CS */
+/*     __raw_writel(0x06697ff4, MSC2); *//* none/SM501 */
+       __raw_writel((__raw_readl(MSC2) & ~0xffff) | 0x7ff4, MSC2); /* SM501 */
 
        pxa_set_ffuart_info(NULL);
        pxa_set_btuart_info(NULL);
@@ -273,7 +274,7 @@ static void __init csb726_init(void)
 
 MACHINE_START(CSB726, "Cogent CSB726")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .init_machine   = csb726_init,
        .timer          = &pxa_timer,
index aaa1166df9640a925e50c822cd3ddd777080b4d6..022c2fa4af04063ebe2334dc19754d4597e7de05 100644 (file)
@@ -342,27 +342,6 @@ struct platform_device pxa27x_device_i2c_power = {
 };
 #endif
 
-#ifdef CONFIG_PXA3xx
-static struct resource pxa3xx_resources_i2c_power[] = {
-       {
-               .start  = 0x40f500c0,
-               .end    = 0x40f500d3,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_PWRI2C,
-               .end    = IRQ_PWRI2C,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device pxa3xx_device_i2c_power = {
-       .name           = "pxa3xx-pwri2c",
-       .id             = 1,
-       .resource       = pxa3xx_resources_i2c_power,
-       .num_resources  = ARRAY_SIZE(pxa3xx_resources_i2c_power),
-};
-#endif
-
 static struct resource pxai2s_resources[] = {
        {
                .start  = 0x40400000,
@@ -633,30 +612,35 @@ struct platform_device pxa25x_device_assp = {
 #endif /* CONFIG_PXA25x */
 
 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
-
-static struct resource pxa27x_resource_keypad[] = {
+static struct resource pxa27x_resource_camera[] = {
        [0] = {
-               .start  = 0x41500000,
-               .end    = 0x4150004c,
+               .start  = 0x50000000,
+               .end    = 0x50000fff,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = IRQ_KEYPAD,
-               .end    = IRQ_KEYPAD,
+               .start  = IRQ_CAMERA,
+               .end    = IRQ_CAMERA,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
-struct platform_device pxa27x_device_keypad = {
-       .name           = "pxa27x-keypad",
-       .id             = -1,
-       .resource       = pxa27x_resource_keypad,
-       .num_resources  = ARRAY_SIZE(pxa27x_resource_keypad),
+static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32);
+
+static struct platform_device pxa27x_device_camera = {
+       .name           = "pxa27x-camera",
+       .id             = 0, /* This is used to put cameras on this interface */
+       .dev            = {
+               .dma_mask               = &pxa27x_dma_mask_camera,
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(pxa27x_resource_camera),
+       .resource       = pxa27x_resource_camera,
 };
 
-void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
+void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
 {
-       pxa_register_device(&pxa27x_device_keypad, info);
+       pxa_register_device(&pxa27x_device_camera, info);
 }
 
 static u64 pxa27x_ohci_dma_mask = DMA_BIT_MASK(32);
@@ -689,6 +673,33 @@ void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
 {
        pxa_register_device(&pxa27x_device_ohci, info);
 }
+#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
+
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+static struct resource pxa27x_resource_keypad[] = {
+       [0] = {
+               .start  = 0x41500000,
+               .end    = 0x4150004c,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_KEYPAD,
+               .end    = IRQ_KEYPAD,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device pxa27x_device_keypad = {
+       .name           = "pxa27x-keypad",
+       .id             = -1,
+       .resource       = pxa27x_resource_keypad,
+       .num_resources  = ARRAY_SIZE(pxa27x_resource_keypad),
+};
+
+void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
+{
+       pxa_register_device(&pxa27x_device_keypad, info);
+}
 
 static u64 pxa27x_ssp1_dma_mask = DMA_BIT_MASK(32);
 
@@ -833,79 +844,9 @@ struct platform_device pxa27x_device_pwm1 = {
        .resource       = pxa27x_resource_pwm1,
        .num_resources  = ARRAY_SIZE(pxa27x_resource_pwm1),
 };
-
-static struct resource pxa27x_resource_camera[] = {
-       [0] = {
-               .start  = 0x50000000,
-               .end    = 0x50000fff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_CAMERA,
-               .end    = IRQ_CAMERA,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32);
-
-static struct platform_device pxa27x_device_camera = {
-       .name           = "pxa27x-camera",
-       .id             = 0, /* This is used to put cameras on this interface */
-       .dev            = {
-               .dma_mask               = &pxa27x_dma_mask_camera,
-               .coherent_dma_mask      = 0xffffffff,
-       },
-       .num_resources  = ARRAY_SIZE(pxa27x_resource_camera),
-       .resource       = pxa27x_resource_camera,
-};
-
-void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
-{
-       pxa_register_device(&pxa27x_device_camera, info);
-}
-#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
+#endif /* CONFIG_PXA27x || CONFIG_PXA3xx || CONFIG_PXA95x*/
 
 #ifdef CONFIG_PXA3xx
-static u64 pxa3xx_ssp4_dma_mask = DMA_BIT_MASK(32);
-
-static struct resource pxa3xx_resource_ssp4[] = {
-       [0] = {
-               .start  = 0x41a00000,
-               .end    = 0x41a0003f,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_SSP4,
-               .end    = IRQ_SSP4,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               /* DRCMR for RX */
-               .start  = 2,
-               .end    = 2,
-               .flags  = IORESOURCE_DMA,
-       },
-       [3] = {
-               /* DRCMR for TX */
-               .start  = 3,
-               .end    = 3,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-struct platform_device pxa3xx_device_ssp4 = {
-       /* PXA3xx SSP is basically equivalent to PXA27x */
-       .name           = "pxa27x-ssp",
-       .id             = 3,
-       .dev            = {
-               .dma_mask = &pxa3xx_ssp4_dma_mask,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-       },
-       .resource       = pxa3xx_resource_ssp4,
-       .num_resources  = ARRAY_SIZE(pxa3xx_resource_ssp4),
-};
-
 static struct resource pxa3xx_resources_mci2[] = {
        [0] = {
                .start  = 0x42000000,
@@ -984,6 +925,54 @@ void __init pxa3xx_set_mci3_info(struct pxamci_platform_data *info)
        pxa_register_device(&pxa3xx_device_mci3, info);
 }
 
+static struct resource pxa3xx_resources_gcu[] = {
+       {
+               .start  = 0x54000000,
+               .end    = 0x54000fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_GCU,
+               .end    = IRQ_GCU,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static u64 pxa3xx_gcu_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device pxa3xx_device_gcu = {
+       .name           = "pxa3xx-gcu",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(pxa3xx_resources_gcu),
+       .resource       = pxa3xx_resources_gcu,
+       .dev            = {
+               .dma_mask = &pxa3xx_gcu_dmamask,
+               .coherent_dma_mask = 0xffffffff,
+       },
+};
+
+#endif /* CONFIG_PXA3xx */
+
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+static struct resource pxa3xx_resources_i2c_power[] = {
+       {
+               .start  = 0x40f500c0,
+               .end    = 0x40f500d3,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_PWRI2C,
+               .end    = IRQ_PWRI2C,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device pxa3xx_device_i2c_power = {
+       .name           = "pxa3xx-pwri2c",
+       .id             = 1,
+       .resource       = pxa3xx_resources_i2c_power,
+       .num_resources  = ARRAY_SIZE(pxa3xx_resources_i2c_power),
+};
+
 static struct resource pxa3xx_resources_nand[] = {
        [0] = {
                .start  = 0x43100000,
@@ -1027,33 +1016,45 @@ void __init pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info)
        pxa_register_device(&pxa3xx_device_nand, info);
 }
 
-static struct resource pxa3xx_resources_gcu[] = {
-       {
-               .start  = 0x54000000,
-               .end    = 0x54000fff,
+static u64 pxa3xx_ssp4_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource pxa3xx_resource_ssp4[] = {
+       [0] = {
+               .start  = 0x41a00000,
+               .end    = 0x41a0003f,
                .flags  = IORESOURCE_MEM,
        },
-       {
-               .start  = IRQ_GCU,
-               .end    = IRQ_GCU,
+       [1] = {
+               .start  = IRQ_SSP4,
+               .end    = IRQ_SSP4,
                .flags  = IORESOURCE_IRQ,
        },
+       [2] = {
+               /* DRCMR for RX */
+               .start  = 2,
+               .end    = 2,
+               .flags  = IORESOURCE_DMA,
+       },
+       [3] = {
+               /* DRCMR for TX */
+               .start  = 3,
+               .end    = 3,
+               .flags  = IORESOURCE_DMA,
+       },
 };
 
-static u64 pxa3xx_gcu_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device pxa3xx_device_gcu = {
-       .name           = "pxa3xx-gcu",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(pxa3xx_resources_gcu),
-       .resource       = pxa3xx_resources_gcu,
+struct platform_device pxa3xx_device_ssp4 = {
+       /* PXA3xx SSP is basically equivalent to PXA27x */
+       .name           = "pxa27x-ssp",
+       .id             = 3,
        .dev            = {
-               .dma_mask = &pxa3xx_gcu_dmamask,
-               .coherent_dma_mask = 0xffffffff,
+               .dma_mask = &pxa3xx_ssp4_dma_mask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
+       .resource       = pxa3xx_resource_ssp4,
+       .num_resources  = ARRAY_SIZE(pxa3xx_resource_ssp4),
 };
-
-#endif /* CONFIG_PXA3xx */
+#endif /* CONFIG_PXA3xx || CONFIG_PXA95x */
 
 /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
  * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
index ed0dbfdb22ed8c0bba1fe048c46151dddcf4482e..4cefd1d18afd5c8d3be2829129e771ced03c3859 100644 (file)
@@ -1300,7 +1300,7 @@ static void __init em_x270_init(void)
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = em_x270_init,
@@ -1308,7 +1308,7 @@ MACHINE_END
 
 MACHINE_START(EXEDA, "Compulab eXeda")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = em_x270_init,
index b25690ccadc4baeebb7da03985bcbf69d66ae3e4..edca0a043293479725052619db8c7be396a44273 100644 (file)
@@ -181,7 +181,7 @@ static void __init e330_init(void)
 MACHINE_START(E330, "Toshiba e330")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
@@ -230,7 +230,7 @@ static void __init e350_init(void)
 MACHINE_START(E350, "Toshiba e350")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
@@ -352,7 +352,7 @@ static void __init e400_init(void)
 MACHINE_START(E400, "Toshiba e400")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
@@ -540,7 +540,7 @@ static void __init e740_init(void)
 MACHINE_START(E740, "Toshiba e740")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
@@ -731,7 +731,7 @@ static void __init e750_init(void)
 MACHINE_START(E750, "Toshiba e750")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
@@ -926,7 +926,7 @@ static void __init e800_init(void)
 MACHINE_START(E800, "Toshiba e800")
        /* Maintainer: Ian Molton (spyro@f2s.com) */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = ESERIES_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .fixup          = eseries_fixup,
index 142c711f4cda0118e4c4aaed5099c7ff6e26ae7d..87cec0abe5b0a3df211c7e9465adce9017ce8492 100644 (file)
@@ -798,7 +798,7 @@ static void __init a780_init(void)
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -863,7 +863,7 @@ static void __init e680_init(void)
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -928,7 +928,7 @@ static void __init a1200_init(void)
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -1118,7 +1118,7 @@ static void __init a910_init(void)
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -1183,7 +1183,7 @@ static void __init e6_init(void)
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -1222,7 +1222,7 @@ static void __init e2_init(void)
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
index 6451e9c3a93fba45a7a1b1d39693dc98f94a40d2..d6e15f71fc09541514b3b803ba2488973b7f6ad6 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <mach/reset.h>
 #include <mach/gpio.h>
+#include <mach/smemc.h>
+#include <mach/pxa3xx-regs.h>
 
 #include "generic.h"
 
@@ -35,9 +37,10 @@ void clear_reset_status(unsigned int mask)
 {
        if (cpu_is_pxa2xx())
                pxa2xx_clear_reset_status(mask);
-
-       if (cpu_is_pxa3xx())
-               pxa3xx_clear_reset_status(mask);
+       else {
+               /* RESET_STATUS_* has a 1:1 mapping with ARSR */
+               ARSR = mask;
+       }
 }
 
 unsigned long get_clock_tick_rate(void)
@@ -70,48 +73,18 @@ unsigned int get_clk_frequency_khz(int info)
 }
 EXPORT_SYMBOL(get_clk_frequency_khz);
 
-/*
- * Return the current memory clock frequency in units of 10kHz
- */
-unsigned int get_memclk_frequency_10khz(void)
-{
-       if (cpu_is_pxa25x())
-               return pxa25x_get_memclk_frequency_10khz();
-       else if (cpu_is_pxa27x())
-               return pxa27x_get_memclk_frequency_10khz();
-       return 0;
-}
-EXPORT_SYMBOL(get_memclk_frequency_10khz);
-
 /*
  * Intel PXA2xx internal register mapping.
  *
- * Note 1: not all PXA2xx variants implement all those addresses.
- *
- * Note 2: virtual 0xfffe0000-0xffffffff is reserved for the vector table
- *         and cache flush area.
+ * Note: virtual 0xfffe0000-0xffffffff is reserved for the vector table
+ *       and cache flush area.
  */
-static struct map_desc standard_io_desc[] __initdata = {
+static struct map_desc common_io_desc[] __initdata = {
        {       /* Devs */
                .virtual        =  0xf2000000,
                .pfn            = __phys_to_pfn(0x40000000),
                .length         = 0x02000000,
                .type           = MT_DEVICE
-       }, {    /* Mem Ctl */
-               .virtual        =  0xf6000000,
-               .pfn            = __phys_to_pfn(0x48000000),
-               .length         = 0x00200000,
-               .type           = MT_DEVICE
-       }, {    /* Camera */
-               .virtual        =  0xfa000000,
-               .pfn            = __phys_to_pfn(0x50000000),
-               .length         = 0x00100000,
-               .type           = MT_DEVICE
-       }, {    /* IMem ctl */
-               .virtual        =  0xfe000000,
-               .pfn            = __phys_to_pfn(0x58000000),
-               .length         = 0x00100000,
-               .type           = MT_DEVICE
        }, {    /* UNCACHED_PHYS_0 */
                .virtual        = 0xff000000,
                .pfn            = __phys_to_pfn(0x00000000),
@@ -122,6 +95,5 @@ static struct map_desc standard_io_desc[] __initdata = {
 
 void __init pxa_map_io(void)
 {
-       iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
-       get_clk_frequency_khz(1);
+       iotable_init(ARRAY_AND_SIZE(common_io_desc));
 }
index 4b1ad2769ed70387fad13ba9e9a775f6e1ce2466..6205dc9a2b9de36285a13efd0d7f9271c309fe0e 100644 (file)
@@ -20,7 +20,12 @@ extern void __init pxa26x_init_irq(void);
 #endif
 extern void __init pxa27x_init_irq(void);
 extern void __init pxa3xx_init_irq(void);
+extern void __init pxa95x_init_irq(void);
+
 extern void __init pxa_map_io(void);
+extern void __init pxa25x_map_io(void);
+extern void __init pxa27x_map_io(void);
+extern void __init pxa3xx_map_io(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
@@ -32,18 +37,14 @@ extern unsigned int get_clk_frequency_khz(int info);
 
 #ifdef CONFIG_PXA25x
 extern unsigned pxa25x_get_clk_frequency_khz(int);
-extern unsigned pxa25x_get_memclk_frequency_10khz(void);
 #else
 #define pxa25x_get_clk_frequency_khz(x)                (0)
-#define pxa25x_get_memclk_frequency_10khz()    (0)
 #endif
 
 #ifdef CONFIG_PXA27x
 extern unsigned pxa27x_get_clk_frequency_khz(int);
-extern unsigned pxa27x_get_memclk_frequency_10khz(void);
 #else
 #define pxa27x_get_clk_frequency_khz(x)                (0)
-#define pxa27x_get_memclk_frequency_10khz()    (0)
 #endif
 
 #if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
@@ -54,10 +55,8 @@ static inline void pxa2xx_clear_reset_status(unsigned int mask) {}
 
 #ifdef CONFIG_PXA3xx
 extern unsigned pxa3xx_get_clk_frequency_khz(int);
-extern void pxa3xx_clear_reset_status(unsigned int);
 #else
 #define pxa3xx_get_clk_frequency_khz(x)                (0)
-static inline void pxa3xx_clear_reset_status(unsigned int mask) {}
 #endif
 
 extern struct sysdev_class pxa_irq_sysclass;
index 1e2a9a13aec143bbb34cdf783bbc8a1a82a5571a..6fd319ea5284b9ca97be0ea333f80c9ced125bd5 100644 (file)
@@ -225,7 +225,7 @@ static void __init gumstix_init(void)
 
 MACHINE_START(GUMSTIX, "Gumstix")
        .boot_params    = 0xa0000100, /* match u-boot bi_boot_params */
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = gumstix_init,
index 7057a1f46db4ed9a35094563216137c80708ade4..657db469de1ff996469ca7e360d548abb4c46666 100644 (file)
@@ -32,6 +32,7 @@
 #include <mach/pxa25x.h>
 #include <mach/h5000.h>
 #include <mach/udc.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 
@@ -172,11 +173,11 @@ static unsigned long h5000_pin_config[] __initdata = {
 
 static void fix_msc(void)
 {
-       MSC0 = 0x129c24f2;
-       MSC1 = 0x7ff424fa;
-       MSC2 = 0x7ff47ff4;
+       __raw_writel(0x129c24f2, MSC0);
+       __raw_writel(0x7ff424fa, MSC1);
+       __raw_writel(0x7ff47ff4, MSC2);
 
-       MDREFR |= 0x02080000;
+       __raw_writel(__raw_readl(MDREFR) | 0x02080000, MDREFR);
 }
 
 /*
@@ -202,7 +203,7 @@ static void __init h5000_init(void)
 
 MACHINE_START(H5400, "HP iPAQ H5000")
        .boot_params = 0xa0000100,
-       .map_io = pxa_map_io,
+       .map_io = pxa25x_map_io,
        .init_irq = pxa25x_init_irq,
        .timer = &pxa_timer,
        .init_machine = h5000_init,
index 01b7f07ebad291d96ceb12cbbf4a5b8cdd9ac77b..e8603eba54bd508e520ee4f60df00edd3187ed8a 100644 (file)
@@ -160,7 +160,7 @@ static void __init himalaya_init(void)
 
 MACHINE_START(HIMALAYA, "HTC Himalaya")
        .boot_params = 0xa0000100,
-       .map_io = pxa_map_io,
+       .map_io = pxa25x_map_io,
        .init_irq = pxa25x_init_irq,
        .init_machine = himalaya_init,
        .timer = &pxa_timer,
index 76d93a25bab62fa33d09cb48965ba1f6267e59a4..cacb21b7014db58a56a6c1c3e7457fdad9cb8669 100644 (file)
@@ -871,7 +871,7 @@ static void __init hx4700_init(void)
 
 MACHINE_START(H4700, "HP iPAQ HX4700")
        .boot_params  = 0xa0000100,
-       .map_io       = pxa_map_io,
+       .map_io       = pxa27x_map_io,
        .nr_irqs      = HX4700_NR_IRQS,
        .init_irq     = pxa27x_init_irq,
        .init_machine = hx4700_init,
index d51ee3d25e7027c8386635940f93a56f89fc7cbf..ac6ee12e400e8870dacf58a4c32b8f7ba82802bd 100644 (file)
@@ -192,7 +192,7 @@ static void __init icontrol_init(void)
 
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = icontrol_init
index e773dceeabc6c8fdc3f5f627147f236118d8a6fd..dd40e4a9291c93478499ab7f12ba9b66c0b820cc 100644 (file)
@@ -187,7 +187,7 @@ static struct map_desc idp_io_desc[] __initdata = {
 
 static void __init idp_map_io(void)
 {
-       pxa_map_io();
+       pxa25x_map_io();
        iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
 }
 
diff --git a/arch/arm/mach-pxa/include/mach/addr-map.h b/arch/arm/mach-pxa/include/mach/addr-map.h
new file mode 100644 (file)
index 0000000..f4c0365
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __ASM_MACH_ADDR_MAP_H
+#define __ASM_MACH_ADDR_MAP_H
+
+/*
+ * Chip Selects
+ */
+#define PXA_CS0_PHYS           0x00000000
+#define PXA_CS1_PHYS           0x04000000
+#define PXA_CS2_PHYS           0x08000000
+#define PXA_CS3_PHYS           0x0C000000
+#define PXA_CS4_PHYS           0x10000000
+#define PXA_CS5_PHYS           0x14000000
+
+#define PXA300_CS0_PHYS                0x00000000      /* PXA300/PXA310 _only_ */
+#define PXA300_CS1_PHYS                0x30000000      /* PXA300/PXA310 _only_ */
+#define PXA3xx_CS2_PHYS                0x10000000
+#define PXA3xx_CS3_PHYS                0x14000000
+
+/*
+ * Peripheral Bus
+ */
+#define PERIPH_PHYS            0x40000000
+#define PERIPH_VIRT            0xf2000000
+#define PERIPH_SIZE            0x02000000
+
+/*
+ * Static Memory Controller (w/ SDRAM controls on PXA25x/PXA27x)
+ */
+#define PXA2XX_SMEMC_PHYS      0x48000000
+#define PXA3XX_SMEMC_PHYS      0x4a000000
+#define SMEMC_VIRT             0xf6000000
+#define SMEMC_SIZE             0x00100000
+
+/*
+ * Dynamic Memory Controller (only on PXA3xx)
+ */
+#define DMEMC_PHYS             0x48100000
+#define DMEMC_VIRT             0xf6100000
+#define DMEMC_SIZE             0x00100000
+
+/*
+ * Internal Memory Controller (PXA27x and later)
+ */
+#define IMEMC_PHYS             0x58000000
+#define IMEMC_VIRT             0xfe000000
+#define IMEMC_SIZE             0x00100000
+
+#endif /* __ASM_MACH_ADDR_MAP_H */
index 561562b4360b7b22477373c8d7fab7a6eb715478..7074e76146c92fc7915954afe15336ecc73ed300 100644 (file)
@@ -26,6 +26,8 @@ enum balloon3_features {
 #define BALLOON3_FPGA_VIRT     (0xf1000000)    /* as per balloon2 */
 #define BALLOON3_FPGA_LENGTH   0x01000000
 
+#define        BALLOON3_FPGA_SETnCLR           (0x1000)
+
 /* FPGA / CPLD registers for CF socket */
 #define        BALLOON3_CF_STATUS_REG          (BALLOON3_FPGA_VIRT + 0x00e00008)
 #define        BALLOON3_CF_CONTROL_REG         (BALLOON3_FPGA_VIRT + 0x00e00008)
@@ -35,7 +37,7 @@ enum balloon3_features {
 #define        BALLOON3_NAND_BASE              (PXA_CS4_PHYS + 0x00e00000)
 #define        BALLOON3_NAND_IO_REG            (BALLOON3_FPGA_VIRT + 0x00e00000)
 #define        BALLOON3_NAND_CONTROL2_REG      (BALLOON3_FPGA_VIRT + 0x00e00010)
-#define        BALLOON3_NAND_STAT_REG          (BALLOON3_FPGA_VIRT + 0x00e00010)
+#define        BALLOON3_NAND_STAT_REG          (BALLOON3_FPGA_VIRT + 0x00e00014)
 #define        BALLOON3_NAND_CONTROL_REG       (BALLOON3_FPGA_VIRT + 0x00e00014)
 
 /* fpga/cpld interrupt control register */
@@ -174,7 +176,7 @@ enum balloon3_features {
 #define BALLOON3_CODEC_IRQ     IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ)
 #define BALLOON3_S0_CD_IRQ     IRQ_GPIO(BALLOON3_GPIO_S0_CD)
 
-#define BALLOON3_NR_IRQS       (IRQ_BOARD_START + 4)
+#define BALLOON3_NR_IRQS       (IRQ_BOARD_START + 16)
 
 extern int balloon3_has(enum balloon3_features feature);
 
index 58dada11054f2deec0102baec6584bd68975b3d4..388a96f1ef93d30cfb6ac84de4828e18585a877f 100644 (file)
@@ -9,14 +9,14 @@
  */
 
 enum {
-       COLIBRI_PXA270_EVALBOARD = 0,
+       COLIBRI_EVALBOARD = 0,
        COLIBRI_PXA270_INCOME,
 };
 
-#if defined(CONFIG_MACH_COLIBRI_PXA270_EVALBOARD)
-extern void colibri_pxa270_evalboard_init(void);
+#if defined(CONFIG_MACH_COLIBRI_EVALBOARD)
+extern void colibri_evalboard_init(void);
 #else
-static inline void colibri_pxa270_evalboard_init(void) {}
+static inline void colibri_evalboard_init(void) {}
 #endif
 
 #if defined(CONFIG_MACH_COLIBRI_PXA270_INCOME)
@@ -59,5 +59,11 @@ static inline void colibri_pxa3xx_init_nand(void) {}
 #define GPIO0_COLIBRI_PXA270_SD_DETECT 0
 #define GPIO113_COLIBRI_PXA270_TS_IRQ  113
 
+/* GPIO definitions for Colibri PXA300/310 */
+#define GPIO39_COLIBRI_PXA300_SD_DETECT        39
+
+/* GPIO definitions for Colibri PXA320 */
+#define GPIO28_COLIBRI_PXA320_SD_DETECT        28
+
 #endif /* _COLIBRI_H_ */
 
index 814f1458a06a52ec5af6b37643ca4b6db602dd55..6957ba56025bb4728313dc7da3694d46ad3a8394 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+#include <mach/addr-map.h>
+
 /*
  * Workarounds for at least 2 errata so far require this.
  * The mapping is set in mach-pxa/generic.c.
 #define __cpu_is_pxa935(id)    (0)
 #endif
 
-#ifdef CONFIG_CPU_PXA950
-#define __cpu_is_pxa950(id)                             \
-       ({                                              \
+#ifdef CONFIG_CPU_PXA955
+#define __cpu_is_pxa955(id)                            \
+       ({                                              \
                unsigned int _id = (id) >> 4 & 0xfff;   \
-               _id == 0x697;                           \
-        })
+               _id == 0x581 || _id == 0xc08            \
+                       || _id == 0xb76;                \
+       })
 #else
-#define __cpu_is_pxa950(id)    (0)
+#define __cpu_is_pxa955(id)    (0)
 #endif
 
 #define cpu_is_pxa210()                                        \
                __cpu_is_pxa935(read_cpuid_id());       \
         })
 
-#define cpu_is_pxa950()                                        \
+#define cpu_is_pxa955()                                        \
        ({                                              \
-               __cpu_is_pxa950(read_cpuid_id());       \
-        })
+               __cpu_is_pxa955(read_cpuid_id());       \
+       })
 
 
 /*
  * CPUID Core Generation Bit
  * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
- * == 0x3 for pxa300/pxa310/pxa320
  */
 #if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
 #define __cpu_is_pxa2xx(id)                            \
 #ifdef CONFIG_PXA3xx
 #define __cpu_is_pxa3xx(id)                            \
        ({                                              \
-               unsigned int _id = (id) >> 13 & 0x7;    \
-               _id == 0x3;                             \
+               __cpu_is_pxa300(id)                     \
+                       || __cpu_is_pxa310(id)          \
+                       || __cpu_is_pxa320(id)          \
+                       || __cpu_is_pxa93x(id);         \
         })
 #else
 #define __cpu_is_pxa3xx(id)    (0)
 #if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935)
 #define __cpu_is_pxa93x(id)                            \
        ({                                              \
-               unsigned int _id = (id) >> 4 & 0xfff;   \
-               _id == 0x683 || _id == 0x693;           \
+               __cpu_is_pxa930(id)                     \
+                       || __cpu_is_pxa935(id);         \
         })
 #else
 #define __cpu_is_pxa93x(id)    (0)
 #endif
 
+#ifdef CONFIG_PXA95x
+#define __cpu_is_pxa95x(id)                            \
+       ({                                              \
+               __cpu_is_pxa955(id);                    \
+       })
+#else
+#define __cpu_is_pxa95x(id)    (0)
+#endif
+
 #define cpu_is_pxa2xx()                                        \
        ({                                              \
                __cpu_is_pxa2xx(read_cpuid_id());       \
        ({                                              \
                __cpu_is_pxa93x(read_cpuid_id());       \
         })
+
+#define cpu_is_pxa95x()                                        \
+       ({                                              \
+               __cpu_is_pxa95x(read_cpuid_id());       \
+       })
+
 /*
  * return current memory and LCD clock frequency in units of 10kHz
  */
index d372caa75dc737d4ca51f4ddcc34c64ac530bd43..a4285fc0087841ad0c48902a2ae5d664f1205745 100644 (file)
 
 #define PXA_IRQ(x)     (PXA_ISA_IRQ_NUM + (x))
 
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 #define IRQ_SSP3       PXA_IRQ(0)      /* SSP3 service request */
 #define IRQ_MSL                PXA_IRQ(1)      /* MSL Interface interrupt */
-#define IRQ_USBH2      PXA_IRQ(2)      /* USB Host interrupt 1 (OHCI) */
-#define IRQ_USBH1      PXA_IRQ(3)      /* USB Host interrupt 2 (non-OHCI) */
+#define IRQ_USBH2      PXA_IRQ(2)      /* USB Host interrupt 1 (OHCI,PXA27x) */
+#define IRQ_USBH1      PXA_IRQ(3)      /* USB Host interrupt 2 (non-OHCI,PXA27x) */
 #define IRQ_KEYPAD     PXA_IRQ(4)      /* Key pad controller */
-#define IRQ_MEMSTK     PXA_IRQ(5)      /* Memory Stick interrupt */
+#define IRQ_MEMSTK     PXA_IRQ(5)      /* Memory Stick interrupt (PXA27x) */
+#define IRQ_ACIPC0     PXA_IRQ(5)      /* AP-CP Communication (PXA930) */
 #define IRQ_PWRI2C     PXA_IRQ(6)      /* Power I2C interrupt */
-#endif
-
 #define IRQ_HWUART     PXA_IRQ(7)      /* HWUART Transmit/Receive/Error (PXA26x) */
 #define IRQ_OST_4_11   PXA_IRQ(7)      /* OS timer 4-11 matches (PXA27x) */
 #define        IRQ_GPIO0       PXA_IRQ(8)      /* GPIO0 Edge Detect */
@@ -38,7 +36,8 @@
 #define        IRQ_GPIO_2_x    PXA_IRQ(10)     /* GPIO[2-x] Edge Detect */
 #define        IRQ_USB         PXA_IRQ(11)     /* USB Service */
 #define        IRQ_PMU         PXA_IRQ(12)     /* Performance Monitoring Unit */
-#define        IRQ_I2S         PXA_IRQ(13)     /* I2S Interrupt */
+#define        IRQ_I2S         PXA_IRQ(13)     /* I2S Interrupt (PXA27x) */
+#define IRQ_SSP4       PXA_IRQ(13)     /* SSP4 service request (PXA3xx) */
 #define        IRQ_AC97        PXA_IRQ(14)     /* AC97 Interrupt */
 #define IRQ_ASSP       PXA_IRQ(15)     /* Audio SSP Service Request (PXA25x) */
 #define IRQ_USIM       PXA_IRQ(15)     /* Smart Card interface interrupt (PXA27x) */
@@ -47,6 +46,7 @@
 #define        IRQ_LCD         PXA_IRQ(17)     /* LCD Controller Service Request */
 #define        IRQ_I2C         PXA_IRQ(18)     /* I2C Service Request */
 #define        IRQ_ICP         PXA_IRQ(19)     /* ICP Transmit/Receive/Error */
+#define IRQ_ACIPC2     PXA_IRQ(19)     /* AP-CP Communication (PXA930) */
 #define        IRQ_STUART      PXA_IRQ(20)     /* STUART Transmit/Receive/Error */
 #define        IRQ_BTUART      PXA_IRQ(21)     /* BTUART Transmit/Receive/Error */
 #define        IRQ_FFUART      PXA_IRQ(22)     /* FFUART Transmit/Receive/Error*/
 #define        IRQ_RTC1Hz      PXA_IRQ(30)     /* RTC HZ Clock Tick */
 #define        IRQ_RTCAlrm     PXA_IRQ(31)     /* RTC Alarm */
 
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 #define IRQ_TPM                PXA_IRQ(32)     /* TPM interrupt */
 #define IRQ_CAMERA     PXA_IRQ(33)     /* Camera Interface */
-#endif
-
-#ifdef CONFIG_PXA3xx
-#define IRQ_SSP4       PXA_IRQ(13)     /* SSP4 service request */
 #define IRQ_CIR                PXA_IRQ(34)     /* Consumer IR */
 #define IRQ_COMM_WDT   PXA_IRQ(35)     /* Comm WDT interrupt */
 #define IRQ_TSI                PXA_IRQ(36)     /* Touch Screen Interface (PXA320) */
+#define IRQ_ENHROT     PXA_IRQ(37)     /* Enhanced Rotary (PXA930) */
 #define IRQ_USIM2      PXA_IRQ(38)     /* USIM2 Controller */
-#define IRQ_GCU                PXA_IRQ(39)     /* Graphics Controller */
+#define IRQ_GCU                PXA_IRQ(39)     /* Graphics Controller (PXA3xx) */
+#define IRQ_ACIPC1     PXA_IRQ(40)     /* AP-CP Communication (PXA930) */
 #define IRQ_MMC2       PXA_IRQ(41)     /* MMC2 Controller */
+#define IRQ_TRKBALL    PXA_IRQ(43)     /* Track Ball (PXA930) */
 #define IRQ_1WIRE      PXA_IRQ(44)     /* 1-Wire Controller */
 #define IRQ_NAND       PXA_IRQ(45)     /* NAND Controller */
 #define IRQ_USB2       PXA_IRQ(46)     /* USB 2.0 Device Controller */
 #define IRQ_WAKEUP1    PXA_IRQ(50)     /* EXT_WAKEUP1 */
 #define IRQ_DMEMC      PXA_IRQ(51)     /* Dynamic Memory Controller */
 #define IRQ_MMC3       PXA_IRQ(55)     /* MMC3 Controller (PXA310) */
-#endif
 
-#ifdef CONFIG_CPU_PXA935
 #define IRQ_U2O                PXA_IRQ(64)     /* USB OTG 2.0 Controller (PXA935) */
 #define IRQ_U2H                PXA_IRQ(65)     /* USB Host 2.0 Controller (PXA935) */
-
-#define IRQ_MMC3_PXA935        PXA_IRQ(72)     /* MMC3 Controller (PXA935) */
-#define IRQ_MMC4_PXA935        PXA_IRQ(73)     /* MMC4 Controller (PXA935) */
-#define IRQ_MMC5_PXA935        PXA_IRQ(74)     /* MMC5 Controller (PXA935) */
-
+#define IRQ_PXA935_MMC0        PXA_IRQ(72)     /* MMC0 Controller (PXA935) */
+#define IRQ_PXA935_MMC1        PXA_IRQ(73)     /* MMC1 Controller (PXA935) */
+#define IRQ_PXA935_MMC2        PXA_IRQ(74)     /* MMC2 Controller (PXA935) */
+#define IRQ_PXA955_MMC3        PXA_IRQ(75)     /* MMC3 Controller (PXA955) */
 #define IRQ_U2P                PXA_IRQ(93)     /* USB PHY D+/D- Lines (PXA935) */
-#endif
-
-#ifdef CONFIG_CPU_PXA930
-#define IRQ_ENHROT     PXA_IRQ(37)     /* Enhanced Rotary (PXA930) */
-#define IRQ_ACIPC0     PXA_IRQ(5)
-#define IRQ_ACIPC1     PXA_IRQ(40)
-#define IRQ_ACIPC2     PXA_IRQ(19)
-#define IRQ_TRKBALL    PXA_IRQ(43)     /* Track Ball */
-#endif
-
-#ifdef CONFIG_CPU_PXA950
-#define IRQ_GC500      PXA_IRQ(70)     /* Graphics Controller (PXA950) */
-#endif
 
 #define PXA_GPIO_IRQ_BASE      PXA_IRQ(96)
 #define PXA_GPIO_IRQ_NUM       (192)
index 4fcddd9cab76988a8556afc708f7f5c5551118aa..ee6ced1cea7f1705cda89be3bff0b3d51356e4cf 100644 (file)
 
 #include <mach/hardware.h>
 
-/*
- * PXA Chip selects
- */
-
-#define PXA_CS0_PHYS   0x00000000
-#define PXA_CS1_PHYS   0x04000000
-#define PXA_CS2_PHYS   0x08000000
-#define PXA_CS3_PHYS   0x0C000000
-#define PXA_CS4_PHYS   0x10000000
-#define PXA_CS5_PHYS   0x14000000
-
-/*
- * Memory controller
- */
-
-#define MDCNFG         __REG(0x48000000)  /* SDRAM Configuration Register 0 */
-#define MDREFR         __REG(0x48000004)  /* SDRAM Refresh Control Register */
-#define MSC0           __REG(0x48000008)  /* Static Memory Control Register 0 */
-#define MSC1           __REG(0x4800000C)  /* Static Memory Control Register 1 */
-#define MSC2           __REG(0x48000010)  /* Static Memory Control Register 2 */
-#define MECR           __REG(0x48000014)  /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
-#define SXLCR          __REG(0x48000018)  /* LCR value to be written to SDRAM-Timing Synchronous Flash */
-#define SXCNFG         __REG(0x4800001C)  /* Synchronous Static Memory Control Register */
-#define SXMRS          __REG(0x48000024)  /* MRS value to be written to Synchronous Flash or SMROM */
-#define MCMEM0         __REG(0x48000028)  /* Card interface Common Memory Space Socket 0 Timing */
-#define MCMEM1         __REG(0x4800002C)  /* Card interface Common Memory Space Socket 1 Timing */
-#define MCATT0         __REG(0x48000030)  /* Card interface Attribute Space Socket 0 Timing Configuration */
-#define MCATT1         __REG(0x48000034)  /* Card interface Attribute Space Socket 1 Timing Configuration */
-#define MCIO0          __REG(0x48000038)  /* Card interface I/O Space Socket 0 Timing Configuration */
-#define MCIO1          __REG(0x4800003C)  /* Card interface I/O Space Socket 1 Timing Configuration */
-#define MDMRS          __REG(0x48000040)  /* MRS value to be written to SDRAM */
-#define BOOT_DEF       __REG(0x48000044)  /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
-
-/*
- * More handy macros for PCMCIA
- *
- * Arg is socket number
- */
-#define MCMEM(s)       __REG2(0x48000028, (s)<<2 )  /* Card interface Common Memory Space Socket s Timing */
-#define MCATT(s)       __REG2(0x48000030, (s)<<2 )  /* Card interface Attribute Space Socket s Timing Configuration */
-#define MCIO(s)                __REG2(0x48000038, (s)<<2 )  /* Card interface I/O Space Socket s Timing Configuration */
-
-/* MECR register defines */
-#define MECR_NOS       (1 << 0)        /* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */
-#define MECR_CIT       (1 << 1)        /* Card Is There: 0 -> no card, 1 -> card inserted */
-
-#define MDCNFG_DE0     (1 << 0)        /* SDRAM Bank 0 Enable */
-#define MDCNFG_DE1     (1 << 1)        /* SDRAM Bank 1 Enable */
-#define MDCNFG_DE2     (1 << 16)       /* SDRAM Bank 2 Enable */
-#define MDCNFG_DE3     (1 << 17)       /* SDRAM Bank 3 Enable */
-
-#define MDREFR_K0DB4   (1 << 29)       /* SDCLK0 Divide by 4 Control/Status */
-#define MDREFR_K2FREE  (1 << 25)       /* SDRAM Free-Running Control */
-#define MDREFR_K1FREE  (1 << 24)       /* SDRAM Free-Running Control */
-#define MDREFR_K0FREE  (1 << 23)       /* SDRAM Free-Running Control */
-#define MDREFR_SLFRSH  (1 << 22)       /* SDRAM Self-Refresh Control/Status */
-#define MDREFR_APD     (1 << 20)       /* SDRAM/SSRAM Auto-Power-Down Enable */
-#define MDREFR_K2DB2   (1 << 19)       /* SDCLK2 Divide by 2 Control/Status */
-#define MDREFR_K2RUN   (1 << 18)       /* SDCLK2 Run Control/Status */
-#define MDREFR_K1DB2   (1 << 17)       /* SDCLK1 Divide by 2 Control/Status */
-#define MDREFR_K1RUN   (1 << 16)       /* SDCLK1 Run Control/Status */
-#define MDREFR_E1PIN   (1 << 15)       /* SDCKE1 Level Control/Status */
-#define MDREFR_K0DB2   (1 << 14)       /* SDCLK0 Divide by 2 Control/Status */
-#define MDREFR_K0RUN   (1 << 13)       /* SDCLK0 Run Control/Status */
-#define MDREFR_E0PIN   (1 << 12)       /* SDCKE0 Level Control/Status */
-
 /*
  * Power Manager
  */
index e91d63cfe811f081aa968c48c7075144593ff823..e4fb4668c26e92646119eea5181ad25d5ec746bb 100644 (file)
 
 #include <mach/hardware.h>
 
-/*
- * Static Chip Selects
- */
-
-#define PXA300_CS0_PHYS                (0x00000000)    /* PXA300/PXA310 _only_ */
-#define PXA300_CS1_PHYS                (0x30000000)    /* PXA300/PXA310 _only_ */
-#define PXA3xx_CS2_PHYS                (0x10000000)
-#define PXA3xx_CS3_PHYS                (0x14000000)
-
 /*
  * Oscillator Configuration Register (OSCC)
  */
index 68464ce1c1ea98c360d203cdb52b17e16acf9d4c..662288eb6f951548abc0fcc8984bcb9b1f36a65f 100644 (file)
@@ -27,8 +27,4 @@
 #define ICFP3          __REG(0x40D0013C)  /* Interrupt Controller FIQ Pending Register 3 */
 #define ICPR3          __REG(0x40D00140)  /* Interrupt Controller Pending Register 3 */
 
-#define IPR(x)         __REG(0x40D0001C + (x < 32 ? (x << 2)           \
-                               : (x < 64 ? (0x94 + ((x - 32) << 2))    \
-                               : (0x128 + ((x - 64) << 2)))))
-
 #endif /* __ASM_MACH_REGS_INTC_H */
diff --git a/arch/arm/mach-pxa/include/mach/smemc.h b/arch/arm/mach-pxa/include/mach/smemc.h
new file mode 100644 (file)
index 0000000..654adc9
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Static memory controller register definitions for PXA CPUs
+ *
+ * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.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 __SMEMC_REGS_H
+#define __SMEMC_REGS_H
+
+#define PXA2XX_SMEMC_BASE      0x48000000
+#define PXA3XX_SMEMC_BASE      0x4a000000
+#define SMEMC_VIRT             0xf6000000
+
+#define MDCNFG         (SMEMC_VIRT + 0x00)  /* SDRAM Configuration Register 0 */
+#define MDREFR         (SMEMC_VIRT + 0x04)  /* SDRAM Refresh Control Register */
+#define MSC0           (SMEMC_VIRT + 0x08)  /* Static Memory Control Register 0 */
+#define MSC1           (SMEMC_VIRT + 0x0C)  /* Static Memory Control Register 1 */
+#define MSC2           (SMEMC_VIRT + 0x10)  /* Static Memory Control Register 2 */
+#define MECR           (SMEMC_VIRT + 0x14)  /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
+#define SXLCR          (SMEMC_VIRT + 0x18)  /* LCR value to be written to SDRAM-Timing Synchronous Flash */
+#define SXCNFG         (SMEMC_VIRT + 0x1C)  /* Synchronous Static Memory Control Register */
+#define SXMRS          (SMEMC_VIRT + 0x24)  /* MRS value to be written to Synchronous Flash or SMROM */
+#define MCMEM0         (SMEMC_VIRT + 0x28)  /* Card interface Common Memory Space Socket 0 Timing */
+#define MCMEM1         (SMEMC_VIRT + 0x2C)  /* Card interface Common Memory Space Socket 1 Timing */
+#define MCATT0         (SMEMC_VIRT + 0x30)  /* Card interface Attribute Space Socket 0 Timing Configuration */
+#define MCATT1         (SMEMC_VIRT + 0x34)  /* Card interface Attribute Space Socket 1 Timing Configuration */
+#define MCIO0          (SMEMC_VIRT + 0x38)  /* Card interface I/O Space Socket 0 Timing Configuration */
+#define MCIO1          (SMEMC_VIRT + 0x3C)  /* Card interface I/O Space Socket 1 Timing Configuration */
+#define MDMRS          (SMEMC_VIRT + 0x40)  /* MRS value to be written to SDRAM */
+#define BOOT_DEF       (SMEMC_VIRT + 0x44)  /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
+#define MEMCLKCFG      (SMEMC_VIRT + 0x68)  /* Clock Configuration */
+#define CSADRCFG0      (SMEMC_VIRT + 0x80)  /* Address Configuration Register for CS0 */
+#define CSADRCFG1      (SMEMC_VIRT + 0x84)  /* Address Configuration Register for CS1 */
+#define CSADRCFG2      (SMEMC_VIRT + 0x88)  /* Address Configuration Register for CS2 */
+#define CSADRCFG3      (SMEMC_VIRT + 0x8C)  /* Address Configuration Register for CS3 */
+
+/*
+ * More handy macros for PCMCIA
+ *
+ * Arg is socket number
+ */
+#define MCMEM(s)       (SMEMC_VIRT + 0x28 + ((s)<<2))  /* Card interface Common Memory Space Socket s Timing */
+#define MCATT(s)       (SMEMC_VIRT + 0x30 + ((s)<<2))  /* Card interface Attribute Space Socket s Timing Configuration */
+#define MCIO(s)                (SMEMC_VIRT + 0x38 + ((s)<<2))  /* Card interface I/O Space Socket s Timing Configuration */
+
+/* MECR register defines */
+#define MECR_NOS       (1 << 0)        /* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */
+#define MECR_CIT       (1 << 1)        /* Card Is There: 0 -> no card, 1 -> card inserted */
+
+#define MDCNFG_DE0     (1 << 0)        /* SDRAM Bank 0 Enable */
+#define MDCNFG_DE1     (1 << 1)        /* SDRAM Bank 1 Enable */
+#define MDCNFG_DE2     (1 << 16)       /* SDRAM Bank 2 Enable */
+#define MDCNFG_DE3     (1 << 17)       /* SDRAM Bank 3 Enable */
+
+#define MDREFR_K0DB4   (1 << 29)       /* SDCLK0 Divide by 4 Control/Status */
+#define MDREFR_K2FREE  (1 << 25)       /* SDRAM Free-Running Control */
+#define MDREFR_K1FREE  (1 << 24)       /* SDRAM Free-Running Control */
+#define MDREFR_K0FREE  (1 << 23)       /* SDRAM Free-Running Control */
+#define MDREFR_SLFRSH  (1 << 22)       /* SDRAM Self-Refresh Control/Status */
+#define MDREFR_APD     (1 << 20)       /* SDRAM/SSRAM Auto-Power-Down Enable */
+#define MDREFR_K2DB2   (1 << 19)       /* SDCLK2 Divide by 2 Control/Status */
+#define MDREFR_K2RUN   (1 << 18)       /* SDCLK2 Run Control/Status */
+#define MDREFR_K1DB2   (1 << 17)       /* SDCLK1 Divide by 2 Control/Status */
+#define MDREFR_K1RUN   (1 << 16)       /* SDCLK1 Run Control/Status */
+#define MDREFR_E1PIN   (1 << 15)       /* SDCKE1 Level Control/Status */
+#define MDREFR_K0DB2   (1 << 14)       /* SDCLK0 Divide by 2 Control/Status */
+#define MDREFR_K0RUN   (1 << 13)       /* SDCLK0 Run Control/Status */
+#define MDREFR_E0PIN   (1 << 12)       /* SDCKE0 Level Control/Status */
+
+#endif
index 1beb40f692fcc93a67e5121335254c58c81bf8bd..54e91c9e71c88727b282a1e1dac3f521738e32c9 100644 (file)
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 
 #include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
+#include <mach/irqs.h>
 #include <mach/gpio.h>
-#include <mach/regs-intc.h>
 
 #include "generic.h"
 
-#define MAX_INTERNAL_IRQS      128
+#define IRQ_BASE               (void __iomem *)io_p2v(0x40d00000)
+
+#define ICIP                   (0x000)
+#define ICMR                   (0x004)
+#define ICLR                   (0x008)
+#define ICFR                   (0x00c)
+#define ICPR                   (0x010)
+#define ICCR                   (0x014)
+#define ICHP                   (0x018)
+#define IPR(i)                 (((i) < 32) ? (0x01c + ((i) << 2)) :            \
+                               ((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) :      \
+                                     (0x144 + (((i) - 64) << 2)))
+#define IPR_VALID              (1 << 31)
+#define IRQ_BIT(n)             (((n) - PXA_IRQ(0)) & 0x1f)
 
-#define IRQ_BIT(n)     (((n) - PXA_IRQ(0)) & 0x1f)
-#define _ICMR(n)       (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
-#define _ICLR(n)       (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))
+#define MAX_INTERNAL_IRQS      128
 
 /*
  * This is for peripheral IRQs internal to the PXA chip.
 
 static int pxa_internal_irq_nr;
 
+static inline int cpu_has_ipr(void)
+{
+       return !cpu_is_pxa25x();
+}
+
 static void pxa_mask_irq(unsigned int irq)
 {
-       _ICMR(irq) &= ~(1 << IRQ_BIT(irq));
+       void __iomem *base = get_irq_chip_data(irq);
+       uint32_t icmr = __raw_readl(base + ICMR);
+
+       icmr &= ~(1 << IRQ_BIT(irq));
+       __raw_writel(icmr, base + ICMR);
 }
 
 static void pxa_unmask_irq(unsigned int irq)
 {
-       _ICMR(irq) |= 1 << IRQ_BIT(irq);
+       void __iomem *base = get_irq_chip_data(irq);
+       uint32_t icmr = __raw_readl(base + ICMR);
+
+       icmr |= 1 << IRQ_BIT(irq);
+       __raw_writel(icmr, base + ICMR);
 }
 
 static struct irq_chip pxa_internal_irq_chip = {
@@ -86,12 +110,16 @@ static void pxa_ack_low_gpio(unsigned int irq)
 
 static void pxa_mask_low_gpio(unsigned int irq)
 {
-       ICMR &= ~(1 << (irq - PXA_IRQ(0)));
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       desc->chip->mask(irq);
 }
 
 static void pxa_unmask_low_gpio(unsigned int irq)
 {
-       ICMR |= 1 << (irq - PXA_IRQ(0));
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       desc->chip->unmask(irq);
 }
 
 static struct irq_chip pxa_low_gpio_chip = {
@@ -120,33 +148,45 @@ static void __init pxa_init_low_gpio_irq(set_wake_t fn)
        pxa_low_gpio_chip.set_wake = fn;
 }
 
+static inline void __iomem *irq_base(int i)
+{
+       static unsigned long phys_base[] = {
+               0x40d00000,
+               0x40d0009c,
+               0x40d00130,
+       };
+
+       return (void __iomem *)io_p2v(phys_base[i >> 5]);
+}
+
 void __init pxa_init_irq(int irq_nr, set_wake_t fn)
 {
-       int irq, i;
+       int irq, i, n;
 
        BUG_ON(irq_nr > MAX_INTERNAL_IRQS);
 
        pxa_internal_irq_nr = irq_nr;
 
-       for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq += 32) {
-               _ICMR(irq) = 0; /* disable all IRQs */
-               _ICLR(irq) = 0; /* all IRQs are IRQ, not FIQ */
-       }
-
-       /* initialize interrupt priority */
-       if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
-               for (i = 0; i < irq_nr; i++)
-                       IPR(i) = i | (1 << 31);
+       for (n = 0; n < irq_nr; n += 32) {
+               void __iomem *base = irq_base(n);
+
+               __raw_writel(0, base + ICMR);   /* disable all IRQs */
+               __raw_writel(0, base + ICLR);   /* all IRQs are IRQ, not FIQ */
+               for (i = n; (i < (n + 32)) && (i < irq_nr); i++) {
+                       /* initialize interrupt priority */
+                       if (cpu_has_ipr())
+                               __raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i));
+
+                       irq = PXA_IRQ(i);
+                       set_irq_chip(irq, &pxa_internal_irq_chip);
+                       set_irq_chip_data(irq, base);
+                       set_irq_handler(irq, handle_level_irq);
+                       set_irq_flags(irq, IRQF_VALID);
+               }
        }
 
        /* only unmasked interrupts kick us out of idle */
-       ICCR = 1;
-
-       for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
-               set_irq_chip(irq, &pxa_internal_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
-               set_irq_flags(irq, IRQF_VALID);
-       }
+       __raw_writel(1, irq_base(0) + ICCR);
 
        pxa_internal_irq_chip.set_wake = fn;
        pxa_init_low_gpio_irq(fn);
@@ -158,16 +198,18 @@ static unsigned long saved_ipr[MAX_INTERNAL_IRQS];
 
 static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
 {
-       int i, irq = PXA_IRQ(0);
+       int i;
 
-       for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
-               saved_icmr[i] = _ICMR(irq);
-               _ICMR(irq) = 0;
+       for (i = 0; i < pxa_internal_irq_nr; i += 32) {
+               void __iomem *base = irq_base(i);
+
+               saved_icmr[i] = __raw_readl(base + ICMR);
+               __raw_writel(0, base + ICMR);
        }
 
-       if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
+       if (cpu_has_ipr()) {
                for (i = 0; i < pxa_internal_irq_nr; i++)
-                       saved_ipr[i] = IPR(i);
+                       saved_ipr[i] = __raw_readl(IRQ_BASE + IPR(i));
        }
 
        return 0;
@@ -175,19 +217,20 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
 
 static int pxa_irq_resume(struct sys_device *dev)
 {
-       int i, irq = PXA_IRQ(0);
+       int i;
 
-       if (cpu_is_pxa27x() || cpu_is_pxa3xx()) {
-               for (i = 0; i < pxa_internal_irq_nr; i++)
-                       IPR(i) = saved_ipr[i];
-       }
+       for (i = 0; i < pxa_internal_irq_nr; i += 32) {
+               void __iomem *base = irq_base(i);
 
-       for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
-               _ICMR(irq) = saved_icmr[i];
-               _ICLR(irq) = 0;
+               __raw_writel(saved_icmr[i], base + ICMR);
+               __raw_writel(0, base + ICLR);
        }
 
-       ICCR = 1;
+       if (!cpu_is_pxa25x())
+               for (i = 0; i < pxa_internal_irq_nr; i++)
+                       __raw_writel(saved_ipr[i], IRQ_BASE + IPR(i));
+
+       __raw_writel(1, IRQ_BASE + ICCR);
        return 0;
 }
 #else
index 41aa89e3577255ecfbec44bfb2cfe4a70540eeab..719c260597e7c01463f757c74b810528fc3e6fce 100644 (file)
@@ -438,7 +438,7 @@ static void __init littleton_init(void)
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .nr_irqs        = LITTLETON_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
index 623af0232a5405d8eb29ab5e3d85df5c028fa42a..8ab62a6778071c00474b62e89f1a051513b09e5f 100644 (file)
@@ -46,6 +46,7 @@
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -463,7 +464,7 @@ static void __init lpd270_init(void)
        pxa_set_btuart_info(NULL);
        pxa_set_stuart_info(NULL);
 
-       lpd270_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+       lpd270_flash_data[0].width = (__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
        lpd270_flash_data[1].width = 4;
 
        /*
@@ -495,7 +496,7 @@ static struct map_desc lpd270_io_desc[] __initdata = {
 
 static void __init lpd270_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
        iotable_init(lpd270_io_desc, ARRAY_SIZE(lpd270_io_desc));
 
        /* for use I SRAM as framebuffer.  */
index 1499493cd070b4636f5eb7bb7abc971cd35f385c..d3375486c8cdf7626743886ab25718557baa6c5a 100644 (file)
@@ -50,6 +50,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/pm.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "clock.h"
@@ -525,7 +526,7 @@ static void __init lubbock_init(void)
        pxa_set_ac97_info(NULL);
 
        lubbock_flash_data[0].width = lubbock_flash_data[1].width =
-               (BOOT_DEF & 1) ? 2 : 4;
+               (__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
        /* Compensate for the nROMBT switch which swaps the flash banks */
        printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
               flashboot?"Flash":"ROM", flashboot);
@@ -549,7 +550,7 @@ static struct map_desc lubbock_io_desc[] __initdata = {
 
 static void __init lubbock_map_io(void)
 {
-       pxa_map_io();
+       pxa25x_map_io();
        iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
 
        PCFR |= PCFR_OPDE;
index 90663760307aac11f4a1e5956ba3d7a1212ad41f..41198f0dc3ac7ad2838f611ad49e458d6c8a8f86 100644 (file)
@@ -765,7 +765,7 @@ static void __init magician_init(void)
 
 MACHINE_START(MAGICIAN, "HTC Magician")
        .boot_params = 0xa0000100,
-       .map_io = pxa_map_io,
+       .map_io = pxa27x_map_io,
        .nr_irqs = MAGICIAN_NR_IRQS,
        .init_irq = pxa27x_init_irq,
        .init_machine = magician_init,
index a980a5c93e49c71e88ff256eefe6715f96d9e965..740c03590e3b89d513b8c22eb29facd60b78e75d 100644 (file)
@@ -51,6 +51,7 @@
 #include <mach/irda.h>
 #include <mach/ohci.h>
 #include <plat/pxa27x_keypad.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -565,7 +566,7 @@ static void __init mainstone_init(void)
        pxa_set_btuart_info(NULL);
        pxa_set_stuart_info(NULL);
 
-       mst_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+       mst_flash_data[0].width = (__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
        mst_flash_data[1].width = 4;
 
        /* Compensate for SW7 which swaps the flash banks */
@@ -614,7 +615,7 @@ static struct map_desc mainstone_io_desc[] __initdata = {
 
 static void __init mainstone_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
        iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
 
        /*      for use I SRAM as framebuffer.  */
index f5fb915e1315e202e1a95528720dc3e445825b2b..faafea3542fbb65edc795cae818cc8fb8f911e90 100644 (file)
@@ -819,7 +819,7 @@ static void mioa701_machine_exit(void)
 
 MACHINE_START(MIOA701, "MIO A701")
        .boot_params    = 0xa0000100,
-       .map_io         = &pxa_map_io,
+       .map_io         = &pxa27x_map_io,
        .init_irq       = &pxa27x_init_irq,
        .init_machine   = mioa701_machine_init,
        .timer          = &pxa_timer,
index 116167aaba685f0848410917531eab8690fae1ae..59cce78aebd19c1850dcaee97ef610fa3c3331a6 100644 (file)
@@ -94,7 +94,7 @@ static void __init mp900c_init(void)
 MACHINE_START(NEC_MP900, "MobilePro900/C")
        .boot_params    = 0xa0220100,
        .timer          = &pxa_timer,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .init_machine   = mp900c_init,
 MACHINE_END
index ce092c521e6df248c470bfe984e08ddac10a0f03..a6f898cbfac91b30b0f82d95a4b9fe5dcb94ea43 100644 (file)
@@ -313,7 +313,7 @@ static struct map_desc palmld_io_desc[] __initdata = {
 
 static void __init palmld_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
        iotable_init(palmld_io_desc, ARRAY_SIZE(palmld_io_desc));
 }
 
index 862da812cd10a61f5d80bef7290626f06bc88491..df4d7d009fbbe72bd59e8650e59f8813c8886d2f 100644 (file)
@@ -203,7 +203,7 @@ static void __init palmt5_init(void)
 
 MACHINE_START(PALMT5, "Palm Tungsten|T5")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .reserve        = palmt5_reserve,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
index 2131d5860919f6df9baa74e9765008936ed0ad69..a09a2374697b6401b86ae7a4e014a93c95f4a44e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/power_supply.h>
 #include <linux/gpio_keys.h>
 #include <linux/mtd/physmap.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -116,6 +117,7 @@ static unsigned long palmtc_pin_config[] __initdata = {
 /******************************************************************************
  * SD/MMC card controller
  ******************************************************************************/
+#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
 static struct pxamci_platform_data palmtc_mci_platform_data = {
        .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
        .gpio_power             = GPIO_NR_PALMTC_SD_POWER,
@@ -124,9 +126,18 @@ static struct pxamci_platform_data palmtc_mci_platform_data = {
        .detect_delay_ms        = 200,
 };
 
+static void __init palmtc_mmc_init(void)
+{
+       pxa_set_mci_info(&palmtc_mci_platform_data);
+}
+#else
+static inline void palmtc_mmc_init(void) {}
+#endif
+
 /******************************************************************************
  * GPIO keys
  ******************************************************************************/
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 static struct gpio_keys_button palmtc_pxa_buttons[] = {
        {KEY_F8, GPIO_NR_PALMTC_HOTSYNC_BUTTON, 1, "HotSync Button", EV_KEY, 1},
 };
@@ -144,9 +155,18 @@ static struct platform_device palmtc_pxa_keys = {
        },
 };
 
+static void __init palmtc_keys_init(void)
+{
+       platform_device_register(&palmtc_pxa_keys);
+}
+#else
+static inline void palmtc_keys_init(void) {}
+#endif
+
 /******************************************************************************
  * Backlight
  ******************************************************************************/
+#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
 static int palmtc_backlight_init(struct device *dev)
 {
        int ret;
@@ -196,17 +216,35 @@ static struct platform_device palmtc_backlight = {
        },
 };
 
+static void __init palmtc_pwm_init(void)
+{
+       platform_device_register(&palmtc_backlight);
+}
+#else
+static inline void palmtc_pwm_init(void) {}
+#endif
+
 /******************************************************************************
  * IrDA
  ******************************************************************************/
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
 static struct pxaficp_platform_data palmtc_ficp_platform_data = {
        .gpio_pwdown            = GPIO_NR_PALMTC_IR_DISABLE,
        .transceiver_cap        = IR_SIRMODE | IR_OFF,
 };
 
+static void __init palmtc_irda_init(void)
+{
+       pxa_set_ficp_info(&palmtc_ficp_platform_data);
+}
+#else
+static inline void palmtc_irda_init(void) {}
+#endif
+
 /******************************************************************************
  * Keyboard
  ******************************************************************************/
+#if defined(CONFIG_KEYBOARD_MATRIX) || defined(CONFIG_KEYBOARD_MATRIX_MODULE)
 static const uint32_t palmtc_matrix_keys[] = {
        KEY(0, 0, KEY_F1),
        KEY(0, 1, KEY_X),
@@ -290,27 +328,103 @@ static struct platform_device palmtc_keyboard = {
                .platform_data = &palmtc_keypad_platform_data,
        },
 };
+static void __init palmtc_mkp_init(void)
+{
+       platform_device_register(&palmtc_keyboard);
+}
+#else
+static inline void palmtc_mkp_init(void) {}
+#endif
 
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmtc_udc_info __initdata = {
+#if defined(CONFIG_USB_GADGET_PXA25X)||defined(CONFIG_USB_GADGET_PXA25X_MODULE)
+static struct gpio_vbus_mach_info palmtc_udc_info = {
        .gpio_vbus              = GPIO_NR_PALMTC_USB_DETECT_N,
        .gpio_vbus_inverted     = 1,
        .gpio_pullup            = GPIO_NR_PALMTC_USB_POWER,
 };
 
+static struct platform_device palmtc_gpio_vbus = {
+       .name   = "gpio-vbus",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &palmtc_udc_info,
+       },
+};
+
+static void __init palmtc_udc_init(void)
+{
+       platform_device_register(&palmtc_gpio_vbus);
+};
+#else
+static inline void palmtc_udc_init(void) {}
+#endif
+
 /******************************************************************************
  * Touchscreen / Battery / GPIO-extender
  ******************************************************************************/
-static struct platform_device palmtc_ucb1400_core = {
+#if    defined(CONFIG_TOUCHSCREEN_UCB1400) || \
+       defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
+static struct platform_device palmtc_ucb1400_device = {
        .name   = "ucb1400_core",
        .id     = -1,
 };
 
+static void __init palmtc_ts_init(void)
+{
+       pxa_set_ac97_info(NULL);
+       platform_device_register(&palmtc_ucb1400_device);
+}
+#else
+static inline void palmtc_ts_init(void) {}
+#endif
+
+/******************************************************************************
+ * LEDs
+ ******************************************************************************/
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+struct gpio_led palmtc_gpio_leds[] = {
+{
+       .name                   = "palmtc:green:user",
+       .default_trigger        = "none",
+       .gpio                   = GPIO_NR_PALMTC_LED_POWER,
+       .active_low             = 1,
+}, {
+       .name                   = "palmtc:vibra:vibra",
+       .default_trigger        = "none",
+       .gpio                   = GPIO_NR_PALMTC_VIBRA_POWER,
+       .active_low             = 1,
+}
+
+};
+
+static struct gpio_led_platform_data palmtc_gpio_led_info = {
+       .leds           = palmtc_gpio_leds,
+       .num_leds       = ARRAY_SIZE(palmtc_gpio_leds),
+};
+
+static struct platform_device palmtc_leds = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &palmtc_gpio_led_info,
+       }
+};
+
+static void __init palmtc_leds_init(void)
+{
+       platform_device_register(&palmtc_leds);
+}
+#else
+static inline void palmtc_leds_init(void) {}
+#endif
+
 /******************************************************************************
  * NOR Flash
  ******************************************************************************/
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
 static struct resource palmtc_flash_resource = {
        .start  = PXA_CS0_PHYS,
        .end    = PXA_CS0_PHYS + SZ_16M - 1,
@@ -356,24 +470,33 @@ static struct platform_device palmtc_flash = {
        },
 };
 
+static void __init palmtc_nor_init(void)
+{
+       platform_device_register(&palmtc_flash);
+}
+#else
+static inline void palmtc_nor_init(void) {}
+#endif
+
 /******************************************************************************
  * Framebuffer
  ******************************************************************************/
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static struct pxafb_mode_info palmtc_lcd_modes[] = {
-{
-       .pixclock       = 115384,
-       .xres           = 320,
-       .yres           = 320,
-       .bpp            = 16,
-
-       .left_margin    = 27,
-       .right_margin   = 7,
-       .upper_margin   = 7,
-       .lower_margin   = 8,
-
-       .hsync_len      = 6,
-       .vsync_len      = 1,
-},
+       {
+               .pixclock       = 115384,
+               .xres           = 320,
+               .yres           = 320,
+               .bpp            = 16,
+
+               .left_margin    = 27,
+               .right_margin   = 7,
+               .upper_margin   = 7,
+               .lower_margin   = 8,
+
+               .hsync_len      = 6,
+               .vsync_len      = 1,
+       },
 };
 
 static struct pxafb_mach_info palmtc_lcd_screen = {
@@ -382,17 +505,17 @@ static struct pxafb_mach_info palmtc_lcd_screen = {
        .lcd_conn               = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
 };
 
+static void __init palmtc_lcd_init(void)
+{
+       set_pxa_fb_info(&palmtc_lcd_screen);
+}
+#else
+static inline void palmtc_lcd_init(void) {}
+#endif
+
 /******************************************************************************
  * Machine init
  ******************************************************************************/
-static struct platform_device *devices[] __initdata = {
-       &palmtc_backlight,
-       &palmtc_ucb1400_core,
-       &palmtc_keyboard,
-       &palmtc_pxa_keys,
-       &palmtc_flash,
-};
-
 static void __init palmtc_init(void)
 {
        pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtc_pin_config));
@@ -402,18 +525,21 @@ static void __init palmtc_init(void)
        pxa_set_stuart_info(NULL);
        pxa_set_hwuart_info(NULL);
 
-       set_pxa_fb_info(&palmtc_lcd_screen);
-       pxa_set_mci_info(&palmtc_mci_platform_data);
-       pxa_set_udc_info(&palmtc_udc_info);
-       pxa_set_ac97_info(NULL);
-       pxa_set_ficp_info(&palmtc_ficp_platform_data);
-
-       platform_add_devices(devices, ARRAY_SIZE(devices));
+       palmtc_mmc_init();
+       palmtc_keys_init();
+       palmtc_pwm_init();
+       palmtc_irda_init();
+       palmtc_mkp_init();
+       palmtc_udc_init();
+       palmtc_ts_init();
+       palmtc_nor_init();
+       palmtc_lcd_init();
+       palmtc_leds_init();
 };
 
 MACHINE_START(PALMTC, "Palm Tungsten|C")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmtc_init
index a9dae7bc35d9ae585299ad4af92904c41ba9f013..3f25014a136c2b2e6b4c9461116b2f5951d3e492 100644 (file)
@@ -374,7 +374,7 @@ static void __init palmte2_init(void)
 
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmte2_init
index 00e2d7ba84ed47c5d93c16bd699c62cdff400269..8aadad55fbe49babfca457c0bb11b5bd444527ab 100644 (file)
@@ -442,7 +442,7 @@ static void __init centro_init(void)
 
 MACHINE_START(TREO680, "Palm Treo 680")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@ -451,7 +451,7 @@ MACHINE_END
 
 MACHINE_START(CENTRO, "Palm Centro 685")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
index d2060a1d1d6820bcaf796e1a256a92989ce45365..595f002066cc0434e734c15831e469acddd9f675 100644 (file)
@@ -241,7 +241,8 @@ static inline void palmtx_keys_init(void) {}
 /******************************************************************************
  * NAND Flash
  ******************************************************************************/
-#if defined(CONFIG_MTD_NAND_GPIO) || defined(CONFIG_MTD_NAND_GPIO_MODULE)
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+       defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
                                 unsigned int ctrl)
 {
@@ -333,7 +334,7 @@ static struct map_desc palmtx_io_desc[] __initdata = {
 
 static void __init palmtx_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
        iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
 }
 
index af6203fbca9caa1a06299490e7aded1e9789e327..7bf4017326e3d8851615b0a51051c8d74b3c6c73 100644 (file)
@@ -280,7 +280,7 @@ static void __init palmz72_init(void)
 
 MACHINE_START(PALMZ72, "Palm Zire72")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = palmz72_init
index c77e8f30a439835c2acd1ea809f9130749ac4c02..8547c9abc40a2e1500ba348682aed7f395596693 100644 (file)
@@ -244,7 +244,7 @@ static void __init pcm027_init(void)
 
 static void __init pcm027_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
 
        /* initialize sleep mode regs (wake-up sources, etc) */
        PGSR0 = 0x01308000;
index 93a191c889df5fa3d440ee269e28894a4e61dbac..8451790cb48d9785d4d5fbccbef1eba12debd268 100644 (file)
@@ -466,7 +466,7 @@ static void __init fixup_poodle(struct machine_desc *desc,
 
 MACHINE_START(POODLE, "SHARP Poodle")
        .fixup          = fixup_poodle,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = POODLE_NR_IRQS,       /* 4 for LoCoMo */
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
index de53f2e4aa390d1cc58b3667f7422aaaeeee81ef..3f5241c84894482477c76cdccee77e02e38b5586 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/suspend.h>
 #include <linux/sysdev.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
@@ -30,6 +31,7 @@
 #include <mach/reset.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -90,23 +92,21 @@ unsigned int pxa25x_get_clk_frequency_khz(int info)
        return (turbo & 1) ? (N/1000) : (M/1000);
 }
 
-/*
- * Return the current memory clock frequency in units of 10kHz
- */
-unsigned int pxa25x_get_memclk_frequency_10khz(void)
+static unsigned long clk_pxa25x_mem_getrate(struct clk *clk)
 {
-       return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
+       return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK;
 }
 
-static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
-{
-       return pxa25x_get_memclk_frequency_10khz() * 10000;
-}
+static const struct clkops clk_pxa25x_mem_ops = {
+       .enable         = clk_dummy_enable,
+       .disable        = clk_dummy_disable,
+       .getrate        = clk_pxa25x_mem_getrate,
+};
 
 static const struct clkops clk_pxa25x_lcd_ops = {
-       .enable         = clk_cken_enable,
-       .disable        = clk_cken_disable,
-       .getrate        = clk_pxa25x_lcd_getrate,
+       .enable         = clk_pxa2xx_cken_enable,
+       .disable        = clk_pxa2xx_cken_disable,
+       .getrate        = clk_pxa25x_mem_getrate,
 };
 
 static unsigned long gpio12_config_32k[] = {
@@ -160,31 +160,30 @@ static const struct clkops clk_pxa25x_gpio11_ops = {
  * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
  * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
  */
-static DEFINE_CKEN(pxa25x_hwuart, HWUART, 14745600, 1);
-
-static struct clk_lookup pxa25x_hwuart_clkreg =
-       INIT_CLKREG(&clk_pxa25x_hwuart, "pxa2xx-uart.3", NULL);
 
 /*
  * PXA 2xx clock declarations.
  */
+static DEFINE_PXA2_CKEN(pxa25x_hwuart, HWUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_ffuart, FFUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_btuart, BTUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_stuart, STUART, 14745600, 1);
+static DEFINE_PXA2_CKEN(pxa25x_usb, USB, 47923000, 5);
+static DEFINE_PXA2_CKEN(pxa25x_mmc, MMC, 19169000, 0);
+static DEFINE_PXA2_CKEN(pxa25x_i2c, I2C, 31949000, 0);
+static DEFINE_PXA2_CKEN(pxa25x_ssp, SSP, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_nssp, NSSP, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_assp, ASSP, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_pwm0, PWM0, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_pwm1, PWM1, 3686400, 0);
+static DEFINE_PXA2_CKEN(pxa25x_ac97, AC97, 24576000, 0);
+static DEFINE_PXA2_CKEN(pxa25x_i2s, I2S, 14745600, 0);
+static DEFINE_PXA2_CKEN(pxa25x_ficp, FICP, 47923000, 0);
+
 static DEFINE_CK(pxa25x_lcd, LCD, &clk_pxa25x_lcd_ops);
-static DEFINE_CKEN(pxa25x_ffuart, FFUART, 14745600, 1);
-static DEFINE_CKEN(pxa25x_btuart, BTUART, 14745600, 1);
-static DEFINE_CKEN(pxa25x_stuart, STUART, 14745600, 1);
-static DEFINE_CKEN(pxa25x_usb, USB, 47923000, 5);
 static DEFINE_CLK(pxa25x_gpio11, &clk_pxa25x_gpio11_ops, 3686400, 0);
 static DEFINE_CLK(pxa25x_gpio12, &clk_pxa25x_gpio12_ops, 32768, 0);
-static DEFINE_CKEN(pxa25x_mmc, MMC, 19169000, 0);
-static DEFINE_CKEN(pxa25x_i2c, I2C, 31949000, 0);
-static DEFINE_CKEN(pxa25x_ssp, SSP, 3686400, 0);
-static DEFINE_CKEN(pxa25x_nssp, NSSP, 3686400, 0);
-static DEFINE_CKEN(pxa25x_assp, ASSP, 3686400, 0);
-static DEFINE_CKEN(pxa25x_pwm0, PWM0, 3686400, 0);
-static DEFINE_CKEN(pxa25x_pwm1, PWM1, 3686400, 0);
-static DEFINE_CKEN(pxa25x_ac97, AC97, 24576000, 0);
-static DEFINE_CKEN(pxa25x_i2s, I2S, 14745600, 0);
-static DEFINE_CKEN(pxa25x_ficp, FICP, 47923000, 0);
+static DEFINE_CLK(pxa25x_mem, &clk_pxa25x_mem_ops, 0, 0);
 
 static struct clk_lookup pxa25x_clkregs[] = {
        INIT_CLKREG(&clk_pxa25x_lcd, "pxa2xx-fb", NULL),
@@ -205,8 +204,12 @@ static struct clk_lookup pxa25x_clkregs[] = {
        INIT_CLKREG(&clk_pxa25x_ac97, NULL, "AC97CLK"),
        INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"),
        INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
+       INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
 };
 
+static struct clk_lookup pxa25x_hwuart_clkreg =
+       INIT_CLKREG(&clk_pxa25x_hwuart, "pxa2xx-uart.3", NULL);
+
 #ifdef CONFIG_PM
 
 #define SAVE(x)                sleep_save[SLEEP_SAVE_##x] = x
@@ -219,20 +222,17 @@ static struct clk_lookup pxa25x_clkregs[] = {
  */
 enum {
        SLEEP_SAVE_PSTR,
-       SLEEP_SAVE_CKEN,
        SLEEP_SAVE_COUNT
 };
 
 
 static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
 {
-       SAVE(CKEN);
        SAVE(PSTR);
 }
 
 static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
 {
-       RESTORE(CKEN);
        RESTORE(PSTR);
 }
 
@@ -320,6 +320,22 @@ void __init pxa26x_init_irq(void)
 }
 #endif
 
+static struct map_desc pxa25x_io_desc[] __initdata = {
+       {       /* Mem Ctl */
+               .virtual        = SMEMC_VIRT,
+               .pfn            = __phys_to_pfn(PXA2XX_SMEMC_BASE),
+               .length         = 0x00200000,
+               .type           = MT_DEVICE
+       },
+};
+
+void __init pxa25x_map_io(void)
+{
+       pxa_map_io();
+       iotable_init(ARRAY_AND_SIZE(pxa25x_io_desc));
+       pxa25x_get_clk_frequency_khz(1);
+}
+
 static struct platform_device *pxa25x_devices[] __initdata = {
        &pxa25x_device_udc,
        &pxa_device_pmu,
@@ -339,7 +355,9 @@ static struct sys_device pxa25x_sysdev[] = {
                .cls    = &pxa2xx_mfp_sysclass,
        }, {
                .cls    = &pxa_gpio_sysclass,
-       },
+       }, {
+               .cls    = &pxa2xx_clock_sysclass,
+       }
 };
 
 static int __init pxa25x_init(void)
index d1fbf29d561c5cbe4b49e634ccb9953f6b1a4f27..b2130b7a7b52c5cc7cfd691eb1490d8f64a6a8e3 100644 (file)
@@ -17,7 +17,9 @@
 #include <linux/suspend.h>
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
+#include <linux/io.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
@@ -27,6 +29,8 @@
 #include <mach/ohci.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
+#include <mach/smemc.h>
+
 #include <plat/i2c.h>
 
 #include "generic.h"
@@ -107,10 +111,9 @@ unsigned int pxa27x_get_clk_frequency_khz(int info)
 }
 
 /*
- * Return the current mem clock frequency in units of 10kHz as
- * reflected by CCCR[A], B, and L
+ * Return the current mem clock frequency as reflected by CCCR[A], B, and L
  */
-unsigned int pxa27x_get_memclk_frequency_10khz(void)
+static unsigned long clk_pxa27x_mem_getrate(struct clk *clk)
 {
        unsigned long ccsr, clkcfg;
        unsigned int l, L, m, M;
@@ -129,9 +132,15 @@ unsigned int pxa27x_get_memclk_frequency_10khz(void)
        L = l * BASE_CLK;
        M = (!cccr_a) ? (L/m) : ((b) ? L : (L/2));
 
-       return (M / 10000);
+       return M;
 }
 
+static const struct clkops clk_pxa27x_mem_ops = {
+       .enable         = clk_dummy_enable,
+       .disable        = clk_dummy_disable,
+       .getrate        = clk_pxa27x_mem_getrate,
+};
+
 /*
  * Return the current LCD clock frequency in units of 10kHz as
  */
@@ -157,36 +166,38 @@ static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk)
 }
 
 static const struct clkops clk_pxa27x_lcd_ops = {
-       .enable         = clk_cken_enable,
-       .disable        = clk_cken_disable,
+       .enable         = clk_pxa2xx_cken_enable,
+       .disable        = clk_pxa2xx_cken_disable,
        .getrate        = clk_pxa27x_lcd_getrate,
 };
 
+static DEFINE_PXA2_CKEN(pxa27x_ffuart, FFUART, 14857000, 1);
+static DEFINE_PXA2_CKEN(pxa27x_btuart, BTUART, 14857000, 1);
+static DEFINE_PXA2_CKEN(pxa27x_stuart, STUART, 14857000, 1);
+static DEFINE_PXA2_CKEN(pxa27x_i2s, I2S, 14682000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_i2c, I2C, 32842000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_usb, USB, 48000000, 5);
+static DEFINE_PXA2_CKEN(pxa27x_mmc, MMC, 19500000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ficp, FICP, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_usbhost, USBHOST, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_pwri2c, PWRI2C, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_keypad, KEYPAD, 32768, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ssp1, SSP1, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ssp2, SSP2, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ssp3, SSP3, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_pwm0, PWM0, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_pwm1, PWM1, 13000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ac97, AC97, 24576000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_ac97conf, AC97CONF, 24576000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_msl, MSL, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_usim, USIM, 48000000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_memstk, MEMSTK, 19500000, 0);
+static DEFINE_PXA2_CKEN(pxa27x_im, IM, 0, 0);
+static DEFINE_PXA2_CKEN(pxa27x_memc, MEMC, 0, 0);
+
 static DEFINE_CK(pxa27x_lcd, LCD, &clk_pxa27x_lcd_ops);
 static DEFINE_CK(pxa27x_camera, CAMERA, &clk_pxa27x_lcd_ops);
-static DEFINE_CKEN(pxa27x_ffuart, FFUART, 14857000, 1);
-static DEFINE_CKEN(pxa27x_btuart, BTUART, 14857000, 1);
-static DEFINE_CKEN(pxa27x_stuart, STUART, 14857000, 1);
-static DEFINE_CKEN(pxa27x_i2s, I2S, 14682000, 0);
-static DEFINE_CKEN(pxa27x_i2c, I2C, 32842000, 0);
-static DEFINE_CKEN(pxa27x_usb, USB, 48000000, 5);
-static DEFINE_CKEN(pxa27x_mmc, MMC, 19500000, 0);
-static DEFINE_CKEN(pxa27x_ficp, FICP, 48000000, 0);
-static DEFINE_CKEN(pxa27x_usbhost, USBHOST, 48000000, 0);
-static DEFINE_CKEN(pxa27x_pwri2c, PWRI2C, 13000000, 0);
-static DEFINE_CKEN(pxa27x_keypad, KEYPAD, 32768, 0);
-static DEFINE_CKEN(pxa27x_ssp1, SSP1, 13000000, 0);
-static DEFINE_CKEN(pxa27x_ssp2, SSP2, 13000000, 0);
-static DEFINE_CKEN(pxa27x_ssp3, SSP3, 13000000, 0);
-static DEFINE_CKEN(pxa27x_pwm0, PWM0, 13000000, 0);
-static DEFINE_CKEN(pxa27x_pwm1, PWM1, 13000000, 0);
-static DEFINE_CKEN(pxa27x_ac97, AC97, 24576000, 0);
-static DEFINE_CKEN(pxa27x_ac97conf, AC97CONF, 24576000, 0);
-static DEFINE_CKEN(pxa27x_msl, MSL, 48000000, 0);
-static DEFINE_CKEN(pxa27x_usim, USIM, 48000000, 0);
-static DEFINE_CKEN(pxa27x_memstk, MEMSTK, 19500000, 0);
-static DEFINE_CKEN(pxa27x_im, IM, 0, 0);
-static DEFINE_CKEN(pxa27x_memc, MEMC, 0, 0);
+static DEFINE_CLK(pxa27x_mem, &clk_pxa27x_mem_ops, 0, 0);
 
 static struct clk_lookup pxa27x_clkregs[] = {
        INIT_CLKREG(&clk_pxa27x_lcd, "pxa2xx-fb", NULL),
@@ -215,6 +226,7 @@ static struct clk_lookup pxa27x_clkregs[] = {
        INIT_CLKREG(&clk_pxa27x_memstk, NULL, "MSTKCLK"),
        INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"),
        INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"),
+       INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL),
 };
 
 #ifdef CONFIG_PM
@@ -246,7 +258,6 @@ int __init pxa27x_set_pwrmode(unsigned int mode)
  */
 enum {
        SLEEP_SAVE_PSTR,
-       SLEEP_SAVE_CKEN,
        SLEEP_SAVE_MDREFR,
        SLEEP_SAVE_PCFR,
        SLEEP_SAVE_COUNT
@@ -254,21 +265,19 @@ enum {
 
 void pxa27x_cpu_pm_save(unsigned long *sleep_save)
 {
-       SAVE(MDREFR);
+       sleep_save[SLEEP_SAVE_MDREFR] = __raw_readl(MDREFR);
        SAVE(PCFR);
 
-       SAVE(CKEN);
        SAVE(PSTR);
 }
 
 void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
 {
-       RESTORE(MDREFR);
+       __raw_writel(sleep_save[SLEEP_SAVE_MDREFR], MDREFR);
        RESTORE(PCFR);
 
        PSSR = PSSR_RDH | PSSR_PH;
 
-       RESTORE(CKEN);
        RESTORE(PSTR);
 }
 
@@ -370,6 +379,27 @@ void __init pxa27x_init_irq(void)
        pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake);
 }
 
+static struct map_desc pxa27x_io_desc[] __initdata = {
+       {       /* Mem Ctl */
+               .virtual        = SMEMC_VIRT,
+               .pfn            = __phys_to_pfn(PXA2XX_SMEMC_BASE),
+               .length         = 0x00200000,
+               .type           = MT_DEVICE
+       }, {    /* IMem ctl */
+               .virtual        =  0xfe000000,
+               .pfn            = __phys_to_pfn(0x58000000),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE
+       },
+};
+
+void __init pxa27x_map_io(void)
+{
+       pxa_map_io();
+       iotable_init(ARRAY_AND_SIZE(pxa27x_io_desc));
+       pxa27x_get_clk_frequency_khz(1);
+}
+
 /*
  * device registration specific to PXA27x.
  */
@@ -405,7 +435,9 @@ static struct sys_device pxa27x_sysdev[] = {
                .cls    = &pxa2xx_mfp_sysclass,
        }, {
                .cls    = &pxa_gpio_sysclass,
-       },
+       }, {
+               .cls    = &pxa2xx_clock_sysclass,
+       }
 };
 
 static int __init pxa27x_init(void)
index d1c747cdacf879f32f947c54795e86ba06435efc..e14818f5d950c3e06468f0124b0ab16e98d368f7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/sysdev.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/regs-intc.h>
+#include <mach/smemc.h>
 #include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
 #include "clock.h"
 
-/* Crystal clock: 13MHz */
-#define BASE_CLK       13000000
-
-/* Ring Oscillator Clock: 60MHz */
-#define RO_CLK         60000000
-
-#define ACCR_D0CS      (1 << 26)
-#define ACCR_PCCE      (1 << 11)
-
 #define PECR_IE(n)     ((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)     ((1 << ((n) * 2)) << 29)
 
-/* crystal frequency to static memory controller multiplier (SMCFS) */
-static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
-
-/* crystal frequency to HSIO bus frequency multiplier (HSS) */
-static unsigned char hss_mult[4] = { 8, 12, 16, 24 };
-
-/*
- * Get the clock frequency as reflected by CCSR and the turbo flag.
- * We assume these values have been applied via a fcs.
- * If info is not 0 we also display the current settings.
- */
-unsigned int pxa3xx_get_clk_frequency_khz(int info)
-{
-       unsigned long acsr, xclkcfg;
-       unsigned int t, xl, xn, hss, ro, XL, XN, CLK, HSS;
-
-       /* Read XCLKCFG register turbo bit */
-       __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
-       t = xclkcfg & 0x1;
-
-       acsr = ACSR;
-
-       xl  = acsr & 0x1f;
-       xn  = (acsr >> 8) & 0x7;
-       hss = (acsr >> 14) & 0x3;
-
-       XL = xl * BASE_CLK;
-       XN = xn * XL;
-
-       ro = acsr & ACCR_D0CS;
-
-       CLK = (ro) ? RO_CLK : ((t) ? XN : XL);
-       HSS = (ro) ? RO_CLK : hss_mult[hss] * BASE_CLK;
-
-       if (info) {
-               pr_info("RO Mode clock: %d.%02dMHz (%sactive)\n",
-                       RO_CLK / 1000000, (RO_CLK % 1000000) / 10000,
-                       (ro) ? "" : "in");
-               pr_info("Run Mode clock: %d.%02dMHz (*%d)\n",
-                       XL / 1000000, (XL % 1000000) / 10000, xl);
-               pr_info("Turbo Mode clock: %d.%02dMHz (*%d, %sactive)\n",
-                       XN / 1000000, (XN % 1000000) / 10000, xn,
-                       (t) ? "" : "in");
-               pr_info("HSIO bus clock: %d.%02dMHz\n",
-                       HSS / 1000000, (HSS % 1000000) / 10000);
-       }
-
-       return CLK / 1000;
-}
-
-void pxa3xx_clear_reset_status(unsigned int mask)
-{
-       /* RESET_STATUS_* has a 1:1 mapping with ARSR */
-       ARSR = mask;
-}
-
-/*
- * Return the current AC97 clock frequency.
- */
-static unsigned long clk_pxa3xx_ac97_getrate(struct clk *clk)
-{
-       unsigned long rate = 312000000;
-       unsigned long ac97_div;
-
-       ac97_div = AC97_DIV;
-
-       /* This may loose precision for some rates but won't for the
-        * standard 24.576MHz.
-        */
-       rate /= (ac97_div >> 12) & 0x7fff;
-       rate *= (ac97_div & 0xfff);
-
-       return rate;
-}
-
-/*
- * Return the current HSIO bus clock frequency
- */
-static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
-{
-       unsigned long acsr;
-       unsigned int hss, hsio_clk;
-
-       acsr = ACSR;
-
-       hss = (acsr >> 14) & 0x3;
-       hsio_clk = (acsr & ACCR_D0CS) ? RO_CLK : hss_mult[hss] * BASE_CLK;
-
-       return hsio_clk;
-}
-
-void clk_pxa3xx_cken_enable(struct clk *clk)
-{
-       unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-       if (clk->cken < 32)
-               CKENA |= mask;
-       else
-               CKENB |= mask;
-}
-
-void clk_pxa3xx_cken_disable(struct clk *clk)
-{
-       unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-       if (clk->cken < 32)
-               CKENA &= ~mask;
-       else
-               CKENB &= ~mask;
-}
-
-const struct clkops clk_pxa3xx_cken_ops = {
-       .enable         = clk_pxa3xx_cken_enable,
-       .disable        = clk_pxa3xx_cken_disable,
-};
-
-static const struct clkops clk_pxa3xx_hsio_ops = {
-       .enable         = clk_pxa3xx_cken_enable,
-       .disable        = clk_pxa3xx_cken_disable,
-       .getrate        = clk_pxa3xx_hsio_getrate,
-};
-
-static const struct clkops clk_pxa3xx_ac97_ops = {
-       .enable         = clk_pxa3xx_cken_enable,
-       .disable        = clk_pxa3xx_cken_disable,
-       .getrate        = clk_pxa3xx_ac97_getrate,
-};
-
-static void clk_pout_enable(struct clk *clk)
-{
-       OSCC |= OSCC_PEN;
-}
-
-static void clk_pout_disable(struct clk *clk)
-{
-       OSCC &= ~OSCC_PEN;
-}
-
-static const struct clkops clk_pout_ops = {
-       .enable         = clk_pout_enable,
-       .disable        = clk_pout_disable,
-};
-
-static void clk_dummy_enable(struct clk *clk)
-{
-}
-
-static void clk_dummy_disable(struct clk *clk)
-{
-}
-
-static const struct clkops clk_dummy_ops = {
-       .enable         = clk_dummy_enable,
-       .disable        = clk_dummy_disable,
-};
-
-static struct clk clk_pxa3xx_pout = {
-       .ops            = &clk_pout_ops,
-       .rate           = 13000000,
-       .delay          = 70,
-};
-
-static struct clk clk_dummy = {
-       .ops            = &clk_dummy_ops,
-};
-
-static DEFINE_PXA3_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops);
-static DEFINE_PXA3_CK(pxa3xx_camera, CAMERA, &clk_pxa3xx_hsio_ops);
-static DEFINE_PXA3_CK(pxa3xx_ac97, AC97, &clk_pxa3xx_ac97_ops);
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
@@ -234,6 +58,12 @@ static DEFINE_PXA3_CKEN(pxa3xx_pwm1, PWM1, 13000000, 0);
 static DEFINE_PXA3_CKEN(pxa3xx_mmc1, MMC1, 19500000, 0);
 static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0);
 
+static DEFINE_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops);
+static DEFINE_CK(pxa3xx_smemc, SMC, &clk_pxa3xx_smemc_ops);
+static DEFINE_CK(pxa3xx_camera, CAMERA, &clk_pxa3xx_hsio_ops);
+static DEFINE_CK(pxa3xx_ac97, AC97, &clk_pxa3xx_ac97_ops);
+static DEFINE_CLK(pxa3xx_pout, &clk_pxa3xx_pout_ops, 13000000, 70);
+
 static struct clk_lookup pxa3xx_clkregs[] = {
        INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
        /* Power I2C clock is always on */
@@ -258,6 +88,7 @@ static struct clk_lookup pxa3xx_clkregs[] = {
        INIT_CLKREG(&clk_pxa3xx_pwm1, "pxa27x-pwm.1", NULL),
        INIT_CLKREG(&clk_pxa3xx_mmc1, "pxa2xx-mci.0", NULL),
        INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL),
+       INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL),
 };
 
 #ifdef CONFIG_PM
@@ -268,30 +99,6 @@ static struct clk_lookup pxa3xx_clkregs[] = {
 static void __iomem *sram;
 static unsigned long wakeup_src;
 
-#define SAVE(x)                sleep_save[SLEEP_SAVE_##x] = x
-#define RESTORE(x)     x = sleep_save[SLEEP_SAVE_##x]
-
-enum { SLEEP_SAVE_CKENA,
-       SLEEP_SAVE_CKENB,
-       SLEEP_SAVE_ACCR,
-
-       SLEEP_SAVE_COUNT,
-};
-
-static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
-{
-       SAVE(CKENA);
-       SAVE(CKENB);
-       SAVE(ACCR);
-}
-
-static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save)
-{
-       RESTORE(ACCR);
-       RESTORE(CKENA);
-       RESTORE(CKENB);
-}
-
 /*
  * Enter a standby mode (S0D1C2 or S0D2C2).  Upon wakeup, the dynamic
  * memory controller has to be reinitialised, so we place some code
@@ -390,9 +197,6 @@ static int pxa3xx_cpu_pm_valid(suspend_state_t state)
 }
 
 static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = {
-       .save_count     = SLEEP_SAVE_COUNT,
-       .save           = pxa3xx_cpu_pm_save,
-       .restore        = pxa3xx_cpu_pm_restore,
        .valid          = pxa3xx_cpu_pm_valid,
        .enter          = pxa3xx_cpu_pm_enter,
 };
@@ -580,6 +384,22 @@ void __init pxa3xx_init_irq(void)
        pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
+static struct map_desc pxa3xx_io_desc[] __initdata = {
+       {       /* Mem Ctl */
+               .virtual        = SMEMC_VIRT,
+               .pfn            = __phys_to_pfn(PXA3XX_SMEMC_BASE),
+               .length         = 0x00200000,
+               .type           = MT_DEVICE
+       }
+};
+
+void __init pxa3xx_map_io(void)
+{
+       pxa_map_io();
+       iotable_init(ARRAY_AND_SIZE(pxa3xx_io_desc));
+       pxa3xx_get_clk_frequency_khz(1);
+}
+
 /*
  * device registration specific to PXA3xx.
  */
@@ -615,7 +435,9 @@ static struct sys_device pxa3xx_sysdev[] = {
                .cls    = &pxa3xx_mfp_sysclass,
        }, {
                .cls    = &pxa_gpio_sysclass,
-       },
+       }, {
+               .cls    = &pxa3xx_clock_sysclass,
+       }
 };
 
 static int __init pxa3xx_init(void)
index 7d29dd3af79d20cb55c1e20296c7f80adcd171f8..8aeacf908784875da9c1e4e47c64ef44c9e4c728 100644 (file)
@@ -192,7 +192,7 @@ static struct mfp_addr_map pxa935_mfp_addr_map[] __initdata = {
 
 static int __init pxa930_init(void)
 {
-       if (cpu_is_pxa930() || cpu_is_pxa935() || cpu_is_pxa950()) {
+       if (cpu_is_pxa93x()) {
                mfp_init_base(io_p2v(MFPR_BASE));
                mfp_init_addr(pxa930_mfp_addr_map);
        }
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
new file mode 100644 (file)
index 0000000..437980f
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa95x.c
+ *
+ * code specific to PXA95x aka MGx
+ *
+ * Copyright (C) 2009-2010 Marvell International 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/pxa930.h>
+#include <mach/reset.h>
+#include <mach/pm.h>
+#include <mach/dma.h>
+#include <mach/regs-intc.h>
+#include <plat/i2c.h>
+
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
+static struct mfp_addr_map pxa95x_mfp_addr_map[] __initdata = {
+
+       MFP_ADDR(GPIO0, 0x02e0),
+       MFP_ADDR(GPIO1, 0x02dc),
+       MFP_ADDR(GPIO2, 0x02e8),
+       MFP_ADDR(GPIO3, 0x02d8),
+       MFP_ADDR(GPIO4, 0x02e4),
+       MFP_ADDR(GPIO5, 0x02ec),
+       MFP_ADDR(GPIO6, 0x02f8),
+       MFP_ADDR(GPIO7, 0x02fc),
+       MFP_ADDR(GPIO8, 0x0300),
+       MFP_ADDR(GPIO9, 0x02d4),
+       MFP_ADDR(GPIO10, 0x02f4),
+       MFP_ADDR(GPIO11, 0x02f0),
+       MFP_ADDR(GPIO12, 0x0304),
+       MFP_ADDR(GPIO13, 0x0310),
+       MFP_ADDR(GPIO14, 0x0308),
+       MFP_ADDR(GPIO15, 0x030c),
+       MFP_ADDR(GPIO16, 0x04e8),
+       MFP_ADDR(GPIO17, 0x04f4),
+       MFP_ADDR(GPIO18, 0x04f8),
+       MFP_ADDR(GPIO19, 0x04fc),
+       MFP_ADDR(GPIO20, 0x0518),
+       MFP_ADDR(GPIO21, 0x051c),
+       MFP_ADDR(GPIO22, 0x04ec),
+       MFP_ADDR(GPIO23, 0x0500),
+       MFP_ADDR(GPIO24, 0x04f0),
+       MFP_ADDR(GPIO25, 0x0504),
+       MFP_ADDR(GPIO26, 0x0510),
+       MFP_ADDR(GPIO27, 0x0514),
+       MFP_ADDR(GPIO28, 0x0520),
+       MFP_ADDR(GPIO29, 0x0600),
+       MFP_ADDR(GPIO30, 0x0618),
+       MFP_ADDR(GPIO31, 0x0610),
+       MFP_ADDR(GPIO32, 0x060c),
+       MFP_ADDR(GPIO33, 0x061c),
+       MFP_ADDR(GPIO34, 0x0620),
+       MFP_ADDR(GPIO35, 0x0628),
+       MFP_ADDR(GPIO36, 0x062c),
+       MFP_ADDR(GPIO37, 0x0630),
+       MFP_ADDR(GPIO38, 0x0634),
+       MFP_ADDR(GPIO39, 0x0638),
+       MFP_ADDR(GPIO40, 0x063c),
+       MFP_ADDR(GPIO41, 0x0614),
+       MFP_ADDR(GPIO42, 0x0624),
+       MFP_ADDR(GPIO43, 0x0608),
+       MFP_ADDR(GPIO44, 0x0604),
+       MFP_ADDR(GPIO45, 0x050c),
+       MFP_ADDR(GPIO46, 0x0508),
+       MFP_ADDR(GPIO47, 0x02bc),
+       MFP_ADDR(GPIO48, 0x02b4),
+       MFP_ADDR(GPIO49, 0x02b8),
+       MFP_ADDR(GPIO50, 0x02c8),
+       MFP_ADDR(GPIO51, 0x02c0),
+       MFP_ADDR(GPIO52, 0x02c4),
+       MFP_ADDR(GPIO53, 0x02d0),
+       MFP_ADDR(GPIO54, 0x02cc),
+       MFP_ADDR(GPIO55, 0x029c),
+       MFP_ADDR(GPIO56, 0x02a0),
+       MFP_ADDR(GPIO57, 0x0294),
+       MFP_ADDR(GPIO58, 0x0298),
+       MFP_ADDR(GPIO59, 0x02a4),
+       MFP_ADDR(GPIO60, 0x02a8),
+       MFP_ADDR(GPIO61, 0x02b0),
+       MFP_ADDR(GPIO62, 0x02ac),
+       MFP_ADDR(GPIO63, 0x0640),
+       MFP_ADDR(GPIO64, 0x065c),
+       MFP_ADDR(GPIO65, 0x0648),
+       MFP_ADDR(GPIO66, 0x0644),
+       MFP_ADDR(GPIO67, 0x0674),
+       MFP_ADDR(GPIO68, 0x0658),
+       MFP_ADDR(GPIO69, 0x0654),
+       MFP_ADDR(GPIO70, 0x0660),
+       MFP_ADDR(GPIO71, 0x0668),
+       MFP_ADDR(GPIO72, 0x0664),
+       MFP_ADDR(GPIO73, 0x0650),
+       MFP_ADDR(GPIO74, 0x066c),
+       MFP_ADDR(GPIO75, 0x064c),
+       MFP_ADDR(GPIO76, 0x0670),
+       MFP_ADDR(GPIO77, 0x0678),
+       MFP_ADDR(GPIO78, 0x067c),
+       MFP_ADDR(GPIO79, 0x0694),
+       MFP_ADDR(GPIO80, 0x069c),
+       MFP_ADDR(GPIO81, 0x06a0),
+       MFP_ADDR(GPIO82, 0x06a4),
+       MFP_ADDR(GPIO83, 0x0698),
+       MFP_ADDR(GPIO84, 0x06bc),
+       MFP_ADDR(GPIO85, 0x06b4),
+       MFP_ADDR(GPIO86, 0x06b0),
+       MFP_ADDR(GPIO87, 0x06c0),
+       MFP_ADDR(GPIO88, 0x06c4),
+       MFP_ADDR(GPIO89, 0x06ac),
+       MFP_ADDR(GPIO90, 0x0680),
+       MFP_ADDR(GPIO91, 0x0684),
+       MFP_ADDR(GPIO92, 0x0688),
+       MFP_ADDR(GPIO93, 0x0690),
+       MFP_ADDR(GPIO94, 0x068c),
+       MFP_ADDR(GPIO95, 0x06a8),
+       MFP_ADDR(GPIO96, 0x06b8),
+       MFP_ADDR(GPIO97, 0x0410),
+       MFP_ADDR(GPIO98, 0x0418),
+       MFP_ADDR(GPIO99, 0x041c),
+       MFP_ADDR(GPIO100, 0x0414),
+       MFP_ADDR(GPIO101, 0x0408),
+       MFP_ADDR(GPIO102, 0x0324),
+       MFP_ADDR(GPIO103, 0x040c),
+       MFP_ADDR(GPIO104, 0x0400),
+       MFP_ADDR(GPIO105, 0x0328),
+       MFP_ADDR(GPIO106, 0x0404),
+
+       MFP_ADDR(GPIO159, 0x0524),
+       MFP_ADDR(GPIO163, 0x0534),
+       MFP_ADDR(GPIO167, 0x0544),
+       MFP_ADDR(GPIO168, 0x0548),
+       MFP_ADDR(GPIO169, 0x054c),
+       MFP_ADDR(GPIO170, 0x0550),
+       MFP_ADDR(GPIO171, 0x0554),
+       MFP_ADDR(GPIO172, 0x0558),
+       MFP_ADDR(GPIO173, 0x055c),
+
+       MFP_ADDR(nXCVREN, 0x0204),
+       MFP_ADDR(DF_CLE_nOE, 0x020c),
+       MFP_ADDR(DF_nADV1_ALE, 0x0218),
+       MFP_ADDR(DF_SCLK_E, 0x0214),
+       MFP_ADDR(DF_SCLK_S, 0x0210),
+       MFP_ADDR(nBE0, 0x021c),
+       MFP_ADDR(nBE1, 0x0220),
+       MFP_ADDR(DF_nADV2_ALE, 0x0224),
+       MFP_ADDR(DF_INT_RnB, 0x0228),
+       MFP_ADDR(DF_nCS0, 0x022c),
+       MFP_ADDR(DF_nCS1, 0x0230),
+       MFP_ADDR(nLUA, 0x0254),
+       MFP_ADDR(nLLA, 0x0258),
+       MFP_ADDR(DF_nWE, 0x0234),
+       MFP_ADDR(DF_nRE_nOE, 0x0238),
+       MFP_ADDR(DF_ADDR0, 0x024c),
+       MFP_ADDR(DF_ADDR1, 0x0250),
+       MFP_ADDR(DF_ADDR2, 0x025c),
+       MFP_ADDR(DF_ADDR3, 0x0260),
+       MFP_ADDR(DF_IO0, 0x023c),
+       MFP_ADDR(DF_IO1, 0x0240),
+       MFP_ADDR(DF_IO2, 0x0244),
+       MFP_ADDR(DF_IO3, 0x0248),
+       MFP_ADDR(DF_IO4, 0x0264),
+       MFP_ADDR(DF_IO5, 0x0268),
+       MFP_ADDR(DF_IO6, 0x026c),
+       MFP_ADDR(DF_IO7, 0x0270),
+       MFP_ADDR(DF_IO8, 0x0274),
+       MFP_ADDR(DF_IO9, 0x0278),
+       MFP_ADDR(DF_IO10, 0x027c),
+       MFP_ADDR(DF_IO11, 0x0280),
+       MFP_ADDR(DF_IO12, 0x0284),
+       MFP_ADDR(DF_IO13, 0x0288),
+       MFP_ADDR(DF_IO14, 0x028c),
+       MFP_ADDR(DF_IO15, 0x0290),
+
+       MFP_ADDR(GSIM_UIO, 0x0314),
+       MFP_ADDR(GSIM_UCLK, 0x0318),
+       MFP_ADDR(GSIM_UDET, 0x031c),
+       MFP_ADDR(GSIM_nURST, 0x0320),
+
+       MFP_ADDR(PMIC_INT, 0x06c8),
+
+       MFP_ADDR(RDY, 0x0200),
+
+       MFP_ADDR_END,
+};
+
+static DEFINE_CK(pxa95x_lcd, LCD, &clk_pxa3xx_hsio_ops);
+static DEFINE_CLK(pxa95x_pout, &clk_pxa3xx_pout_ops, 13000000, 70);
+static DEFINE_PXA3_CKEN(pxa95x_ffuart, FFUART, 14857000, 1);
+static DEFINE_PXA3_CKEN(pxa95x_btuart, BTUART, 14857000, 1);
+static DEFINE_PXA3_CKEN(pxa95x_stuart, STUART, 14857000, 1);
+static DEFINE_PXA3_CKEN(pxa95x_i2c, I2C, 32842000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_keypad, KEYPAD, 32768, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp1, SSP1, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp2, SSP2, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp3, SSP3, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_ssp4, SSP4, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_pwm0, PWM0, 13000000, 0);
+static DEFINE_PXA3_CKEN(pxa95x_pwm1, PWM1, 13000000, 0);
+
+static struct clk_lookup pxa95x_clkregs[] = {
+       INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"),
+       /* Power I2C clock is always on */
+       INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
+       INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL),
+       INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL),
+       INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL),
+       INIT_CLKREG(&clk_pxa95x_stuart, "pxa2xx-uart.2", NULL),
+       INIT_CLKREG(&clk_pxa95x_stuart, "pxa2xx-ir", "UARTCLK"),
+       INIT_CLKREG(&clk_pxa95x_i2c, "pxa2xx-i2c.0", NULL),
+       INIT_CLKREG(&clk_pxa95x_keypad, "pxa27x-keypad", NULL),
+       INIT_CLKREG(&clk_pxa95x_ssp1, "pxa27x-ssp.0", NULL),
+       INIT_CLKREG(&clk_pxa95x_ssp2, "pxa27x-ssp.1", NULL),
+       INIT_CLKREG(&clk_pxa95x_ssp3, "pxa27x-ssp.2", NULL),
+       INIT_CLKREG(&clk_pxa95x_ssp4, "pxa27x-ssp.3", NULL),
+       INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL),
+       INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL),
+};
+
+void __init pxa95x_init_irq(void)
+{
+       pxa_init_irq(96, NULL);
+       pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
+}
+
+/*
+ * device registration specific to PXA93x.
+ */
+
+void __init pxa95x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
+{
+       pxa_register_device(&pxa3xx_device_i2c_power, info);
+}
+
+static struct platform_device *devices[] __initdata = {
+       &sa1100_device_rtc,
+       &pxa_device_rtc,
+       &pxa27x_device_ssp1,
+       &pxa27x_device_ssp2,
+       &pxa27x_device_ssp3,
+       &pxa3xx_device_ssp4,
+       &pxa27x_device_pwm0,
+       &pxa27x_device_pwm1,
+};
+
+static struct sys_device pxa95x_sysdev[] = {
+       {
+               .cls    = &pxa_irq_sysclass,
+       }, {
+               .cls    = &pxa_gpio_sysclass,
+       }, {
+               .cls    = &pxa3xx_clock_sysclass,
+       }
+};
+
+static int __init pxa95x_init(void)
+{
+       int ret = 0, i;
+
+       if (cpu_is_pxa95x()) {
+               mfp_init_base(io_p2v(MFPR_BASE));
+               mfp_init_addr(pxa95x_mfp_addr_map);
+
+               reset_status = ARSR;
+
+               /*
+                * clear RDH bit every time after reset
+                *
+                * Note: the last 3 bits DxS are write-1-to-clear so carefully
+                * preserve them here in case they will be referenced later
+                */
+               ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
+
+               clkdev_add_table(pxa95x_clkregs, ARRAY_SIZE(pxa95x_clkregs));
+
+               if ((ret = pxa_init_dma(IRQ_DMA, 32)))
+                       return ret;
+
+               for (i = 0; i < ARRAY_SIZE(pxa95x_sysdev); i++) {
+                       ret = sysdev_register(&pxa95x_sysdev[i]);
+                       if (ret)
+                               pr_err("failed to register sysdev[%d]\n", i);
+               }
+
+               ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+       }
+
+       return ret;
+}
+
+postcore_initcall(pxa95x_init);
index 4121d03ea2c3eecaa39c7c340ac0a92455adf3de..8361151be054174d85c64e96ba7403671d450767 100644 (file)
@@ -588,6 +588,9 @@ static struct pxafb_mach_info raumfeld_sharp_lcd_info = {
        .num_modes      = 1,
        .video_mem_size = 0x400000,
        .lcd_conn       = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+#ifdef CONFIG_PXA3XX_GCU
+       .acceleration_enabled = 1,
+#endif
 };
 
 static void __init raumfeld_lcd_init(void)
@@ -616,6 +619,8 @@ static void __init raumfeld_lcd_init(void)
                pr_warning("Unable to request GPIO_DISPLAY_ENABLE\n");
        else
                gpio_direction_output(GPIO_DISPLAY_ENABLE, 1);
+
+       platform_device_register(&pxa3xx_device_gcu);
 }
 
 /**
@@ -1085,7 +1090,7 @@ static void __init raumfeld_speaker_init(void)
 MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
        .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
        .init_machine   = raumfeld_controller_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -1095,7 +1100,7 @@ MACHINE_END
 MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
        .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
        .init_machine   = raumfeld_connector_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
@@ -1105,7 +1110,7 @@ MACHINE_END
 MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
        .boot_params    = RAUMFELD_SDRAM_BASE + 0x100,
        .init_machine   = raumfeld_speaker_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
index ffa50e633ee6856b88901228f46b6f21d527cc2f..c1ca8cb467fcc354f4456331f65e4caf34fe1af3 100644 (file)
@@ -597,7 +597,7 @@ static void __init saar_init(void)
 MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = saar_init,
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
new file mode 100644 (file)
index 0000000..e497922
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  linux/arch/arm/mach-pxa/saarb.c
+ *
+ *  Support for the Marvell Handheld Platform (aka SAARB)
+ *
+ *  Copyright (C) 2007-2010 Marvell International 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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/mfd/88pm860x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/mfp.h>
+#include <mach/mfp-pxa930.h>
+#include <mach/gpio.h>
+
+#include <plat/i2c.h>
+
+#include "generic.h"
+
+#define SAARB_NR_IRQS  (IRQ_BOARD_START + 40)
+
+static struct pm860x_touch_pdata saarb_touch = {
+       .gpadc_prebias  = 1,
+       .slot_cycle     = 1,
+       .tsi_prebias    = 6,
+       .pen_prebias    = 16,
+       .pen_prechg     = 2,
+       .res_x          = 300,
+};
+
+static struct pm860x_backlight_pdata saarb_backlight[] = {
+       {
+               .id     = PM8606_ID_BACKLIGHT,
+               .iset   = PM8606_WLED_CURRENT(24),
+               .flags  = PM8606_BACKLIGHT1,
+       },
+       {},
+};
+
+static struct pm860x_led_pdata saarb_led[] = {
+       {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED1_RED,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED1_GREEN,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED1_BLUE,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED2_RED,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED2_GREEN,
+       }, {
+               .id     = PM8606_ID_LED,
+               .iset   = PM8606_LED_CURRENT(12),
+               .flags  = PM8606_LED2_BLUE,
+       },
+};
+
+static struct pm860x_platform_data saarb_pm8607_info = {
+       .touch          = &saarb_touch,
+       .backlight      = &saarb_backlight[0],
+       .led            = &saarb_led[0],
+       .companion_addr = 0x10,
+       .irq_mode       = 0,
+       .irq_base       = IRQ_BOARD_START,
+
+       .i2c_port       = GI2C_PORT,
+};
+
+static struct i2c_board_info saarb_i2c_info[] = {
+       {
+               .type           = "88PM860x",
+               .addr           = 0x34,
+               .platform_data  = &saarb_pm8607_info,
+               .irq            = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)),
+       },
+};
+
+static void __init saarb_init(void)
+{
+       pxa_set_ffuart_info(NULL);
+       pxa_set_i2c_info(NULL);
+       i2c_register_board_info(0, ARRAY_AND_SIZE(saarb_i2c_info));
+}
+
+MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
+       .boot_params    = 0xa0000100,
+       .map_io         = pxa_map_io,
+       .nr_irqs        = SAARB_NR_IRQS,
+       .init_irq       = pxa95x_init_irq,
+       .timer          = &pxa_timer,
+       .init_machine   = saarb_init,
+MACHINE_END
+
index 52c30b01a67139e88fdb71af7dd7371525167bfd..2f5b08aeb52e8c0297f79f6015cbbc0e60acca1c 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/hardware.h>
-
+#include <mach/smemc.h>
 #include <mach/pxa2xx-regs.h>
 
 #define MDREFR_KDIV    0x200a4000      // all banks
index d6f6904132a62328895909c7ab39df69daf26b79..232b7316ec08aa1c1de7e913b01fdef069ad5b84 100644 (file)
@@ -9,50 +9,37 @@
 #include <linux/sysdev.h>
 
 #include <mach/hardware.h>
-
-#define SMEMC_PHYS_BASE        (0x4A000000)
-#define SMEMC_PHYS_SIZE        (0x90)
-
-#define MSC0           (0x08)  /* Static Memory Controller Register 0 */
-#define MSC1           (0x0C)  /* Static Memory Controller Register 1 */
-#define SXCNFG         (0x1C)  /* Synchronous Static Memory Control Register */
-#define MEMCLKCFG      (0x68)  /* Clock Configuration */
-#define CSADRCFG0      (0x80)  /* Address Configuration Register for CS0 */
-#define CSADRCFG1      (0x84)  /* Address Configuration Register for CS1 */
-#define CSADRCFG2      (0x88)  /* Address Configuration Register for CS2 */
-#define CSADRCFG3      (0x8C)  /* Address Configuration Register for CS3 */
+#include <mach/smemc.h>
 
 #ifdef CONFIG_PM
-static void __iomem *smemc_mmio_base;
-
 static unsigned long msc[2];
 static unsigned long sxcnfg, memclkcfg;
 static unsigned long csadrcfg[4];
 
 static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
 {
-       msc[0] = __raw_readl(smemc_mmio_base + MSC0);
-       msc[1] = __raw_readl(smemc_mmio_base + MSC1);
-       sxcnfg = __raw_readl(smemc_mmio_base + SXCNFG);
-       memclkcfg = __raw_readl(smemc_mmio_base + MEMCLKCFG);
-       csadrcfg[0] = __raw_readl(smemc_mmio_base + CSADRCFG0);
-       csadrcfg[1] = __raw_readl(smemc_mmio_base + CSADRCFG1);
-       csadrcfg[2] = __raw_readl(smemc_mmio_base + CSADRCFG2);
-       csadrcfg[3] = __raw_readl(smemc_mmio_base + CSADRCFG3);
+       msc[0] = __raw_readl(MSC0);
+       msc[1] = __raw_readl(MSC1);
+       sxcnfg = __raw_readl(SXCNFG);
+       memclkcfg = __raw_readl(MEMCLKCFG);
+       csadrcfg[0] = __raw_readl(CSADRCFG0);
+       csadrcfg[1] = __raw_readl(CSADRCFG1);
+       csadrcfg[2] = __raw_readl(CSADRCFG2);
+       csadrcfg[3] = __raw_readl(CSADRCFG3);
 
        return 0;
 }
 
 static int pxa3xx_smemc_resume(struct sys_device *dev)
 {
-       __raw_writel(msc[0], smemc_mmio_base + MSC0);
-       __raw_writel(msc[1], smemc_mmio_base + MSC1);
-       __raw_writel(sxcnfg, smemc_mmio_base + SXCNFG);
-       __raw_writel(memclkcfg, smemc_mmio_base + MEMCLKCFG);
-       __raw_writel(csadrcfg[0], smemc_mmio_base + CSADRCFG0);
-       __raw_writel(csadrcfg[1], smemc_mmio_base + CSADRCFG1);
-       __raw_writel(csadrcfg[2], smemc_mmio_base + CSADRCFG2);
-       __raw_writel(csadrcfg[3], smemc_mmio_base + CSADRCFG3);
+       __raw_writel(msc[0], MSC0);
+       __raw_writel(msc[1], MSC1);
+       __raw_writel(sxcnfg, SXCNFG);
+       __raw_writel(memclkcfg, MEMCLKCFG);
+       __raw_writel(csadrcfg[0], CSADRCFG0);
+       __raw_writel(csadrcfg[1], CSADRCFG1);
+       __raw_writel(csadrcfg[2], CSADRCFG2);
+       __raw_writel(csadrcfg[3], CSADRCFG3);
 
        return 0;
 }
@@ -73,10 +60,6 @@ static int __init smemc_init(void)
        int ret = 0;
 
        if (cpu_is_pxa3xx()) {
-               smemc_mmio_base = ioremap(SMEMC_PHYS_BASE, SMEMC_PHYS_SIZE);
-               if (smemc_mmio_base == NULL)
-                       return -ENODEV;
-
                ret = sysdev_class_register(&smemc_sysclass);
                if (ret)
                        return ret;
index f736119f1ebfd46c59b7904e13685fc159b245dd..0499a69e76733d07aedc78f8bf9e95b324f04392 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
+#include <linux/io.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -44,6 +45,7 @@
 #include <mach/pxa2xx_spi.h>
 #include <mach/spitz.h>
 #include <mach/sharpsl_pm.h>
+#include <mach/smemc.h>
 
 #include <plat/i2c.h>
 
@@ -929,9 +931,10 @@ static void spitz_poweroff(void)
 
 static void spitz_restart(char mode, const char *cmd)
 {
+       uint32_t msc0 = __raw_readl(MSC0);
        /* Bootloader magic for a reboot */
-       if ((MSC0 & 0xffff0000) == 0x7ff00000)
-               MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+       if ((msc0 & 0xffff0000) == 0x7ff00000)
+               __raw_writel((msc0 & 0xffff) | 0x7ee00000, MSC0);
 
        spitz_poweroff();
 }
@@ -980,7 +983,7 @@ static void __init spitz_fixup(struct machine_desc *desc,
 #ifdef CONFIG_MACH_SPITZ
 MACHINE_START(SPITZ, "SHARP Spitz")
        .fixup          = spitz_fixup,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
@@ -990,7 +993,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_BORZOI
 MACHINE_START(BORZOI, "SHARP Borzoi")
        .fixup          = spitz_fixup,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
@@ -1000,7 +1003,7 @@ MACHINE_END
 #ifdef CONFIG_MACH_AKITA
 MACHINE_START(AKITA, "SHARP Akita")
        .fixup          = spitz_fixup,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .init_machine   = spitz_init,
        .timer          = &pxa_timer,
index 738adc1773fdf643cfc4a81c662fd10da0b2bc8e..3498a1423943474307a207fc0f526f9007848cd4 100644 (file)
@@ -48,6 +48,7 @@
 #include <mach/udc.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/pxa27x-udc.h>
+#include <mach/smemc.h>
 
 #include <linux/spi/spi.h>
 #include <linux/mfd/da903x.h>
@@ -976,7 +977,7 @@ static void __init stargate2_init(void)
 {
        /* This is probably a board specific hack as this must be set
           prior to connecting the MFP stuff up. */
-       MECR &= ~MECR_NOS;
+       __raw_writel(__raw_readl(MECR) & ~MECR_NOS, MECR);
 
        pxa2xx_mfp_config(ARRAY_AND_SIZE(stargate2_pin_config));
 
@@ -998,7 +999,7 @@ static void __init stargate2_init(void)
 
 #ifdef CONFIG_MACH_INTELMOTE2
 MACHINE_START(INTELMOTE2, "IMOTE 2")
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = imote2_init,
@@ -1008,7 +1009,7 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_STARGATE2
 MACHINE_START(STARGATE2, "Stargate 2")
-       .map_io = pxa_map_io,
+       .map_io = pxa27x_map_io,
        .nr_irqs = STARGATE_NR_IRQS,
        .init_irq = pxa27x_init_irq,
        .timer = &pxa_timer,
index 2ea7545273ad949e2b07fd2f107ef2e40a114eaf..9cecf8366db8d2aab57ef25e4f3853137640f9d2 100644 (file)
@@ -490,7 +490,7 @@ static void __init tavorevb_init(void)
 MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = tavorevb_init,
index dc3011697bbfd20e471d17e7dce5b4a664fb3a95..70191a9450eb279e2b4b31b70489716e83424b5a 100644 (file)
@@ -127,7 +127,7 @@ static void __init evb3_init(void)
 
 MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .nr_irqs        = TAVOREVB3_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
index 0ee1df49606db3e33a03c76e0889dc7cc50907d0..57d61ee9b22604d82a911264b4ebbbebfcf585ab 100644 (file)
@@ -46,6 +46,7 @@
 #include <mach/tosa_bt.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/audio.h>
+#include <mach/smemc.h>
 
 #include <asm/mach/arch.h>
 #include <mach/tosa.h>
@@ -893,9 +894,11 @@ static void tosa_poweroff(void)
 
 static void tosa_restart(char mode, const char *cmd)
 {
+       uint32_t msc0 = __raw_readl(MSC0);
+
        /* Bootloader magic for a reboot */
-       if((MSC0 & 0xffff0000) == 0x7ff00000)
-               MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+       if((msc0 & 0xffff0000) == 0x7ff00000)
+               __raw_writel((msc0 & 0xffff) | 0x7ee00000, MSC0);
 
        tosa_poweroff();
 }
@@ -953,7 +956,7 @@ static void __init fixup_tosa(struct machine_desc *desc,
 
 MACHINE_START(TOSA, "SHARP Tosa")
        .fixup          = fixup_tosa,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .nr_irqs        = TOSA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .init_machine   = tosa_init,
index 565d062f51d58fe740ace0ec28108990a910e1d7..43fc9ca14594995b43d68cba6ec9c0471dc833fe 100644 (file)
@@ -47,6 +47,7 @@
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
+#include <mach/smemc.h>
 #include <plat/i2c.h>
 
 #include "generic.h"
@@ -539,10 +540,10 @@ static void __init trizeps4_init(void)
 
 static void __init trizeps4_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
        iotable_init(trizeps4_io_desc, ARRAY_SIZE(trizeps4_io_desc));
 
-       if ((MSC0 & 0x8) && (BOOT_DEF & 0x1)) {
+       if ((__raw_readl(MSC0) & 0x8) && (__raw_readl(BOOT_DEF) & 0x1)) {
                /* if flash is 16 bit wide its a Trizeps4 WL */
                __machine_arch_type = MACH_TYPE_TRIZEPS4WL;
                trizeps4_flash_data[0].width = 2;
index 438fc9a5ed59f625c21a4c6940f96c1020ad71cf..de69b203afa78f0be6ef41c66c0384894d645889 100644 (file)
@@ -983,7 +983,7 @@ static struct map_desc viper_io_desc[] __initdata = {
 
 static void __init viper_map_io(void)
 {
-       pxa_map_io();
+       pxa25x_map_io();
 
        iotable_init(viper_io_desc, ARRAY_SIZE(viper_io_desc));
 
index f45ac0961778776e1e9cc34ea540ab1825a4a013..b9b579715ff65e9e65ea2de154273435e16250fc 100644 (file)
@@ -719,7 +719,7 @@ static void __init vpac270_init(void)
 
 MACHINE_START(VPAC270, "Voipac PXA270")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = vpac270_init
index 3260ce73d327202b5e83b7de7789ae7bab0a9b65..51c0281c6e0a8cb8f946e443b5431fd9939953b6 100644 (file)
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa25x.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 
@@ -172,9 +173,9 @@ static void __init xcep_init(void)
 
        /* See Intel XScale Developer's Guide for details */
        /* Set RDF and RDN to appropriate values (chip select 3 (smc91x)) */
-       MSC1 = (MSC1 & 0xffff) | 0xD5540000;
+       __raw_writel((__raw_readl(MSC1) & 0xffff) | 0xD5540000, MSC1);
        /* Set RDF and RDN to appropriate values (chip select 5 (fpga)) */
-       MSC2 = (MSC2 & 0xffff) | 0x72A00000;
+       __raw_writel((__raw_readl(MSC2) & 0xffff) | 0x72A00000, MSC2);
 
        platform_add_devices(ARRAY_AND_SIZE(devices));
        pxa_set_i2c_info(&xcep_i2c_platform_data);
@@ -183,7 +184,7 @@ static void __init xcep_init(void)
 MACHINE_START(XCEP, "Iskratel XCEP")
        .boot_params    = 0xa0000100,
        .init_machine   = xcep_init,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa25x_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
 MACHINE_END
index fefde9848d82349e08554dd74b3fea9d7f9cbd1e..527c2a1ed310e0f5e1d83dec0438e301be20156c 100644 (file)
@@ -704,7 +704,7 @@ static void __init z2_init(void)
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa27x_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = z2_init,
index dea46a2d089b8a6f6d42040f8fd2debcf1b2d1c6..c87f2b35ee05223702c50d8df0e8e02d9b66e467 100644 (file)
@@ -47,6 +47,7 @@
 #include <mach/audio.h>
 #include <mach/arcom-pcmcia.h>
 #include <mach/zeus.h>
+#include <mach/smemc.h>
 
 #include "generic.h"
 
@@ -823,13 +824,16 @@ static mfp_cfg_t zeus_pin_config[] __initdata = {
 static void __init zeus_init(void)
 {
        u16 dm9000_msc = DM9K_MSC_VALUE;
+       u32 msc0, msc1;
 
        system_rev = __raw_readw(ZEUS_CPLD_VERSION);
        pr_info("Zeus CPLD V%dI%d\n", (system_rev & 0xf0) >> 4, (system_rev & 0x0f));
 
        /* Fix timings for dm9000s (CS1/CS2)*/
-       MSC0 = (MSC0 & 0xffff) | (dm9000_msc << 16);
-       MSC1 = (MSC1 & 0xffff0000) | dm9000_msc;
+       msc0 = __raw_readl(MSC0) & 0x0000ffff | (dm9000_msc << 16);
+       msc1 = __raw_readl(MSC1) & 0xffff0000 | dm9000_msc;
+       __raw_writel(msc0, MSC0);
+       __raw_writel(msc1, MSC1);
 
        pm_power_off = zeus_power_off;
        zeus_setup_apm();
@@ -883,7 +887,7 @@ static struct map_desc zeus_io_desc[] __initdata = {
 
 static void __init zeus_map_io(void)
 {
-       pxa_map_io();
+       pxa27x_map_io();
 
        iotable_init(zeus_io_desc, ARRAY_SIZE(zeus_io_desc));
 
index 702f7a68e87d593f18bb60ef54091cec561726c1..a4c784aab7649b98b528cbbd2021d4044b2467e3 100644 (file)
@@ -423,7 +423,7 @@ static void __init zylonite_init(void)
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
        .boot_params    = 0xa0000100,
-       .map_io         = pxa_map_io,
+       .map_io         = pxa3xx_map_io,
        .nr_irqs        = ZYLONITE_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .timer          = &pxa_timer,
index cef6a65637bd946c31e12691ba51d2d05f554f6a..fa2e5bffbb8eaa37c6d4db06a2213fb476115c64 100644 (file)
@@ -16,7 +16,7 @@ config CPU_S3C2412
 config CPU_S3C2412_ONLY
        bool
        depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
-                  !CPU_2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
+                  !CPU_S3C2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
                   !CPU_S3C2443 && CPU_S3C2412
        default y if CPU_S3C2412
 
index 87b9c9f003bd503dec247cfa3f51b6a43fd97f36..27b3e7c9d61366edcdc59f234e563cec3b5b6b2b 100644 (file)
@@ -35,9 +35,12 @@ menu "S3C2416 Machines"
 config MACH_SMDK2416
        bool "SMDK2416"
        select CPU_S3C2416
+       select MACH_SMDK
        select S3C_DEV_FB
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC1
+       select S3C_DEV_NAND
+       select S3C_DEV_USB_HOST
        select S3C2416_PM if PM
        help
          Say Y here if you are using an SMDK2416
index ff024a6c0f85cd46ca45959dc7137cdb5f20693e..a0cb2581894fa9fbe322347de25781e7b9a4ba81 100644 (file)
@@ -18,6 +18,7 @@ config CPU_S3C2440
 config CPU_S3C2442
        bool
        select CPU_ARM920T
+       select S3C_GPIO_PULL_DOWN
        select S3C2410_CLOCK
        select S3C2410_GPIO
        select S3C2410_PM if PM
@@ -178,6 +179,9 @@ config MACH_MINI2440
        bool "MINI2440 development board"
        select CPU_S3C2440
        select EEPROM_AT24
+       select NEW_LEDS
+       select LEDS_CLASS
+       select LEDS_TRIGGER
        select LEDS_TRIGGER_BACKLIGHT
        select S3C_DEV_NAND
        select S3C_DEV_USB_HOST
index d50f3ae6173d72a27d71ddefc941e0d1adc6bbec..f7663f731ea0728137700c3ada958800a54296db 100644 (file)
@@ -46,9 +46,6 @@ int __init s3c2440_init(void)
 {
        printk("S3C2440: Initialising architecture\n");
 
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
-
        /* change irq for watchdog */
 
        s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
@@ -58,3 +55,11 @@ int __init s3c2440_init(void)
 
        return sysdev_register(&s3c2440_sysdev);
 }
+
+void __init s3c2440_map_io(void)
+{
+       s3c244x_map_io();
+
+       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
+       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+}
index 188ad1e57dc0321a1f63254f1f1e2a7c04820a17..ecf813546554739e4d329114a0896c6d49a37288 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mutex.h>
+#include <linux/gpio.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
 
 #include <plat/clock.h>
 #include <plat/cpu.h>
+#include <plat/s3c244x.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
 
 /* S3C2442 extended clock support */
 
@@ -163,3 +169,11 @@ int __init s3c2442_init(void)
 
        return sysdev_register(&s3c2442_sysdev);
 }
+
+void __init s3c2442_map_io(void)
+{
+       s3c244x_map_io();
+
+       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down;
+       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down;
+}
index 4fef723126fa3223e4c45711d80e610907208f19..31babec90cecc9b92ff4a08b00da33c8a8446833 100644 (file)
@@ -5,6 +5,7 @@
 config CPU_S3C2443
        bool
        depends on ARCH_S3C2410
+       select CPU_ARM920T
        select S3C2443_DMA if S3C2410_DMA
        select CPU_LLSERIAL_S3C2440
        select SAMSUNG_CLKSRC
index 9e27a84433cbd27829e3099b120c39099bee56cf..12052e8e064cc8ab9400825423ad3e6aecc13733 100644 (file)
@@ -2,14 +2,16 @@
 # Makefile for the linux kernel, U8500 machine.
 #
 
-obj-y                          := clock.o cpu.o devices.o
-obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o
+obj-y                          := clock.o cpu.o devices.o devices-common.o
+obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o
-obj-$(CONFIG_MACH_U8500_MOP)   += board-mop500.o board-mop500-sdi.o
-obj-$(CONFIG_MACH_U5500)       += board-u5500.o
+obj-$(CONFIG_MACH_U8500_MOP)   += board-mop500.o board-mop500-sdi.o \
+                               board-mop500-keypads.o
+obj-$(CONFIG_MACH_U5500)       += board-u5500.o board-u5500-sdi.o
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)      += hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)     += localtimer.o
 obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o
-obj-$(CONFIG_U5500_MODEM_IRQ)  += modem_irq.o
-obj-$(CONFIG_U5500_MBOX)       += mbox.o
+obj-$(CONFIG_U5500_MODEM_IRQ)  += modem-irq-db5500.o
+obj-$(CONFIG_U5500_MBOX)       += mbox-db5500.o
+obj-$(CONFIG_CPU_FREQ)         += cpufreq.o
diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c
new file mode 100644 (file)
index 0000000..70318c3
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Keypad layouts for various boards
+ */
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/mfd/tc3589x.h>
+#include <linux/input/matrix_keypad.h>
+
+#include <plat/pincfg.h>
+#include <plat/ske.h>
+
+#include <mach/devices.h>
+#include <mach/hardware.h>
+
+#include "devices-db8500.h"
+#include "board-mop500.h"
+
+/* STMPE/SKE keypad use this key layout */
+static const unsigned int mop500_keymap[] = {
+       KEY(2, 5, KEY_END),
+       KEY(4, 1, KEY_POWER),
+       KEY(3, 5, KEY_VOLUMEDOWN),
+       KEY(1, 3, KEY_3),
+       KEY(5, 2, KEY_RIGHT),
+       KEY(5, 0, KEY_9),
+
+       KEY(0, 5, KEY_MENU),
+       KEY(7, 6, KEY_ENTER),
+       KEY(4, 5, KEY_0),
+       KEY(6, 7, KEY_2),
+       KEY(3, 4, KEY_UP),
+       KEY(3, 3, KEY_DOWN),
+
+       KEY(6, 4, KEY_SEND),
+       KEY(6, 2, KEY_BACK),
+       KEY(4, 2, KEY_VOLUMEUP),
+       KEY(5, 5, KEY_1),
+       KEY(4, 3, KEY_LEFT),
+       KEY(3, 2, KEY_7),
+};
+
+static const struct matrix_keymap_data mop500_keymap_data = {
+       .keymap         = mop500_keymap,
+       .keymap_size    = ARRAY_SIZE(mop500_keymap),
+};
+
+/*
+ * Nomadik SKE keypad
+ */
+#define ROW_PIN_I0      164
+#define ROW_PIN_I1      163
+#define ROW_PIN_I2      162
+#define ROW_PIN_I3      161
+#define ROW_PIN_I4      156
+#define ROW_PIN_I5      155
+#define ROW_PIN_I6      154
+#define ROW_PIN_I7      153
+#define COL_PIN_O0      168
+#define COL_PIN_O1      167
+#define COL_PIN_O2      166
+#define COL_PIN_O3      165
+#define COL_PIN_O4      160
+#define COL_PIN_O5      159
+#define COL_PIN_O6      158
+#define COL_PIN_O7      157
+
+#define SKE_KPD_MAX_ROWS       8
+#define SKE_KPD_MAX_COLS       8
+
+static int ske_kp_rows[] = {
+       ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
+       ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
+};
+
+/*
+ * ske_set_gpio_row: request and set gpio rows
+ */
+static int ske_set_gpio_row(int gpio)
+{
+       int ret;
+
+       ret = gpio_request(gpio, "ske-kp");
+       if (ret < 0) {
+               pr_err("ske_set_gpio_row: gpio request failed\n");
+               return ret;
+       }
+
+       ret = gpio_direction_output(gpio, 1);
+       if (ret < 0) {
+               pr_err("ske_set_gpio_row: gpio direction failed\n");
+               gpio_free(gpio);
+       }
+
+       return ret;
+}
+
+/*
+ * ske_kp_init - enable the gpio configuration
+ */
+static int ske_kp_init(void)
+{
+       int ret, i;
+
+       for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
+               ret = ske_set_gpio_row(ske_kp_rows[i]);
+               if (ret < 0) {
+                       pr_err("ske_kp_init: failed init\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static struct ske_keypad_platform_data ske_keypad_board = {
+       .init           = ske_kp_init,
+       .keymap_data    = &mop500_keymap_data,
+       .no_autorepeat  = true,
+       .krow           = SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
+       .kcol           = SKE_KPD_MAX_COLS,
+       .debounce_ms    = 40,                   /* in millisecs */
+};
+
+/*
+ * STMPE1601
+ */
+static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
+       .debounce_ms    = 64,
+       .scan_count     = 8,
+       .no_autorepeat  = true,
+       .keymap_data    = &mop500_keymap_data,
+};
+
+static struct stmpe_platform_data stmpe1601_data = {
+       .id             = 1,
+       .blocks         = STMPE_BLOCK_KEYPAD,
+       .irq_trigger    = IRQF_TRIGGER_FALLING,
+       .irq_base       = MOP500_STMPE1601_IRQ(0),
+       .keypad         = &stmpe1601_keypad_data,
+       .autosleep      = true,
+       .autosleep_timeout = 1024,
+};
+
+static struct i2c_board_info mop500_i2c0_devices_stuib[] = {
+       {
+               I2C_BOARD_INFO("stmpe1601", 0x40),
+               .irq = NOMADIK_GPIO_TO_IRQ(218),
+               .platform_data = &stmpe1601_data,
+               .flags = I2C_CLIENT_WAKE,
+       },
+};
+
+/*
+ * TC35893
+ */
+
+static const unsigned int uib_keymap[] = {
+       KEY(3, 1, KEY_END),
+       KEY(4, 1, KEY_POWER),
+       KEY(6, 4, KEY_VOLUMEDOWN),
+       KEY(4, 2, KEY_EMAIL),
+       KEY(3, 3, KEY_RIGHT),
+       KEY(2, 5, KEY_BACKSPACE),
+
+       KEY(6, 7, KEY_MENU),
+       KEY(5, 0, KEY_ENTER),
+       KEY(4, 3, KEY_0),
+       KEY(3, 4, KEY_DOT),
+       KEY(5, 2, KEY_UP),
+       KEY(3, 5, KEY_DOWN),
+
+       KEY(4, 5, KEY_SEND),
+       KEY(0, 5, KEY_BACK),
+       KEY(6, 2, KEY_VOLUMEUP),
+       KEY(1, 3, KEY_SPACE),
+       KEY(7, 6, KEY_LEFT),
+       KEY(5, 5, KEY_SEARCH),
+};
+
+static struct matrix_keymap_data uib_keymap_data = {
+       .keymap         = uib_keymap,
+       .keymap_size    = ARRAY_SIZE(uib_keymap),
+};
+
+static struct tc3589x_keypad_platform_data tc35893_data = {
+       .krow = TC_KPD_ROWS,
+       .kcol = TC_KPD_COLUMNS,
+       .debounce_period = TC_KPD_DEBOUNCE_PERIOD,
+       .settle_time = TC_KPD_SETTLE_TIME,
+       .irqtype = IRQF_TRIGGER_FALLING,
+       .enable_wakeup = true,
+       .keymap_data    = &uib_keymap_data,
+       .no_autorepeat  = true,
+};
+
+static struct tc3589x_platform_data tc3589x_keypad_data = {
+       .block = TC3589x_BLOCK_KEYPAD,
+       .keypad = &tc35893_data,
+       .irq_base = MOP500_EGPIO_IRQ_BASE,
+};
+
+static struct i2c_board_info mop500_i2c0_devices_uib[] = {
+       {
+               I2C_BOARD_INFO("tc3589x", 0x44),
+               .platform_data = &tc3589x_keypad_data,
+               .irq = NOMADIK_GPIO_TO_IRQ(218),
+               .flags = I2C_CLIENT_WAKE,
+       },
+};
+
+void mop500_keypad_init(void)
+{
+       db8500_add_ske_keypad(&ske_keypad_board);
+
+       i2c_register_board_info(0, mop500_i2c0_devices_stuib,
+                       ARRAY_SIZE(mop500_i2c0_devices_stuib));
+
+       i2c_register_board_info(0, mop500_i2c0_devices_uib,
+                       ARRAY_SIZE(mop500_i2c0_devices_uib));
+
+}
index bac995665b58728c98f935c4291c902a26594401..4b996676594e588150a889d4760a6171492d7844 100644 (file)
 #include <mach/devices.h>
 #include <mach/hardware.h>
 
+#include "devices-db8500.h"
 #include "pins-db8500.h"
 #include "board-mop500.h"
 
 static pin_cfg_t mop500_sdi_pins[] = {
+       /* SDI0 (MicroSD slot) */
+       GPIO18_MC0_CMDDIR,
+       GPIO19_MC0_DAT0DIR,
+       GPIO20_MC0_DAT2DIR,
+       GPIO21_MC0_DAT31DIR,
+       GPIO22_MC0_FBCLK,
+       GPIO23_MC0_CLK,
+       GPIO24_MC0_CMD,
+       GPIO25_MC0_DAT0,
+       GPIO26_MC0_DAT1,
+       GPIO27_MC0_DAT2,
+       GPIO28_MC0_DAT3,
+
        /* SDI4 (on-board eMMC) */
        GPIO197_MC4_DAT3,
        GPIO198_MC4_DAT2,
@@ -49,6 +63,55 @@ static pin_cfg_t mop500_sdi2_pins[] = {
        GPIO138_MC2_DAT7,
 };
 
+/*
+ * SDI 0 (MicroSD slot)
+ */
+
+/* MMCIPOWER bits */
+#define MCI_DATA2DIREN         (1 << 2)
+#define MCI_CMDDIREN           (1 << 3)
+#define MCI_DATA0DIREN         (1 << 4)
+#define MCI_DATA31DIREN                (1 << 5)
+#define MCI_FBCLKEN            (1 << 7)
+
+static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
+                                  unsigned char power_mode)
+{
+       if (power_mode == MMC_POWER_UP)
+               gpio_set_value_cansleep(GPIO_SDMMC_EN, 1);
+       else if (power_mode == MMC_POWER_OFF)
+               gpio_set_value_cansleep(GPIO_SDMMC_EN, 0);
+
+       return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
+              MCI_DATA2DIREN | MCI_DATA31DIREN;
+}
+
+static struct mmci_platform_data mop500_sdi0_data = {
+       .vdd_handler    = mop500_sdi0_vdd_handler,
+       .ocr_mask       = MMC_VDD_29_30,
+       .f_max          = 100000000,
+       .capabilities   = MMC_CAP_4_BIT_DATA,
+       .gpio_cd        = GPIO_SDMMC_CD,
+       .gpio_wp        = -1,
+};
+
+void mop500_sdi_tc35892_init(void)
+{
+       int ret;
+
+       ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN");
+       if (!ret)
+               ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL,
+                                  "GPIO_SDMMC_1V8_3V_SEL");
+       if (ret)
+               return;
+
+       gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1);
+       gpio_direction_output(GPIO_SDMMC_EN, 0);
+
+       db8500_add_sdi0(&mop500_sdi0_data);
+}
+
 /*
  * SDI 2 (POP eMMC, not on DB8500ed)
  */
@@ -74,18 +137,24 @@ static struct mmci_platform_data mop500_sdi4_data = {
        .gpio_wp        = -1,
 };
 
-void mop500_sdi_init(void)
+void __init mop500_sdi_init(void)
 {
        nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
 
-       u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data;
-       u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data;
+       /*
+        * sdi0 will finally be added when the TC35892 initializes and calls
+        * mop500_sdi_tc35892_init() above.
+        */
 
+       /* PoP:ed eMMC */
        if (!cpu_is_u8500ed()) {
                nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
-               amba_device_register(&u8500_sdi2_device, &iomem_resource);
+               /* POP eMMC on v1.0 has problems with high speed */
+               if (!cpu_is_u8500v10())
+                       mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+               db8500_add_sdi2(&mop500_sdi2_data);
        }
 
        /* On-board eMMC */
-       amba_device_register(&u8500_sdi4_device, &iomem_resource);
+       db8500_add_sdi4(&mop500_sdi4_data);
 }
index cac83a694880f6dd6d17a62d39387cbf58128144..a1c9ea1a66df65edcf223206fce760697edfd9e3 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
-#include <linux/input/matrix_keypad.h>
+#include <linux/mfd/tc3589x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include <plat/pincfg.h>
 #include <plat/i2c.h>
-#include <plat/ske.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
 #include <mach/irqs.h>
 
+#include "devices-db8500.h"
 #include "pins-db8500.h"
 #include "board-mop500.h"
 
@@ -69,22 +70,12 @@ static pin_cfg_t mop500_pins[] = {
        GPIO166_KP_O2,
        GPIO167_KP_O1,
        GPIO168_KP_O0,
-};
 
-static void ab4500_spi_cs_control(u32 command)
-{
-       /* set the FRM signal, which is CS  - TODO */
-}
+       /* GPIO_EXP_INT */
+       GPIO217_GPIO,
 
-struct pl022_config_chip ab4500_chip_info = {
-       .com_mode = INTERRUPT_TRANSFER,
-       .iface = SSP_INTERFACE_MOTOROLA_SPI,
-       /* we can act as master only */
-       .hierarchy = SSP_MASTER,
-       .slave_tx_disable = 0,
-       .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
-       .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-       .cs_control = ab4500_spi_cs_control,
+       /* STMPE1601 IRQ */
+       GPIO218_GPIO    | PIN_INPUT_PULLUP,
 };
 
 static struct ab8500_platform_data ab8500_platdata = {
@@ -93,9 +84,9 @@ static struct ab8500_platform_data ab8500_platdata = {
 
 static struct resource ab8500_resources[] = {
        [0] = {
-               .start = IRQ_AB8500,
-               .end = IRQ_AB8500,
-               .flags = IORESOURCE_IRQ
+               .start  = IRQ_DB8500_AB8500,
+               .end    = IRQ_DB8500_AB8500,
+               .flags  = IORESOURCE_IRQ
        }
 };
 
@@ -109,19 +100,6 @@ struct platform_device ab8500_device = {
        .resource = ab8500_resources,
 };
 
-static struct spi_board_info ab8500_spi_devices[] = {
-       {
-               .modalias = "ab8500-spi",
-               .controller_data = &ab4500_chip_info,
-               .platform_data = &ab8500_platdata,
-               .max_speed_hz = 12000000,
-               .bus_num = 0,
-               .chip_select = 0,
-               .mode = SPI_MODE_3,
-               .irq = IRQ_DB8500_AB8500,
-       },
-};
-
 static struct pl022_ssp_controller ssp0_platform_data = {
        .bus_id = 0,
        /* pl022 not yet supports dma */
@@ -132,6 +110,34 @@ static struct pl022_ssp_controller ssp0_platform_data = {
        .num_chipselect = 5,
 };
 
+/*
+ * TC35892
+ */
+
+static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base)
+{
+       mop500_sdi_tc35892_init();
+}
+
+static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = {
+       .gpio_base      = MOP500_EGPIO(0),
+       .setup          = mop500_tc35892_init,
+};
+
+static struct tc3589x_platform_data mop500_tc35892_data = {
+       .block          = TC3589x_BLOCK_GPIO,
+       .gpio           = &mop500_tc35892_gpio_data,
+       .irq_base       = MOP500_EGPIO_IRQ_BASE,
+};
+
+static struct i2c_board_info mop500_i2c0_devices[] = {
+       {
+               I2C_BOARD_INFO("tc3589x", 0x42),
+               .irq            = NOMADIK_GPIO_TO_IRQ(217),
+               .platform_data  = &mop500_tc35892_data,
+       },
+};
+
 #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
 static struct nmk_i2c_controller u8500_i2c##id##_data = { \
        /*                              \
@@ -161,159 +167,49 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
 U8500_I2C_CONTROLLER(2,        0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
 U8500_I2C_CONTROLLER(3,        0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
 
-static struct amba_device *amba_devs[] __initdata = {
-       &ux500_uart0_device,
-       &ux500_uart1_device,
-       &ux500_uart2_device,
-       &u8500_ssp0_device,
-};
-
-static const unsigned int ux500_keymap[] = {
-       KEY(2, 5, KEY_END),
-       KEY(4, 1, KEY_POWER),
-       KEY(3, 5, KEY_VOLUMEDOWN),
-       KEY(1, 3, KEY_3),
-       KEY(5, 2, KEY_RIGHT),
-       KEY(5, 0, KEY_9),
-
-       KEY(0, 5, KEY_MENU),
-       KEY(7, 6, KEY_ENTER),
-       KEY(4, 5, KEY_0),
-       KEY(6, 7, KEY_2),
-       KEY(3, 4, KEY_UP),
-       KEY(3, 3, KEY_DOWN),
-
-       KEY(6, 4, KEY_SEND),
-       KEY(6, 2, KEY_BACK),
-       KEY(4, 2, KEY_VOLUMEUP),
-       KEY(5, 5, KEY_1),
-       KEY(4, 3, KEY_LEFT),
-       KEY(3, 2, KEY_7),
-};
-
-static const struct matrix_keymap_data ux500_keymap_data = {
-       .keymap         = ux500_keymap,
-       .keymap_size    = ARRAY_SIZE(ux500_keymap),
-};
+static void __init mop500_i2c_init(void)
+{
+       db8500_add_i2c0(&u8500_i2c0_data);
+       db8500_add_i2c1(&u8500_i2c1_data);
+       db8500_add_i2c2(&u8500_i2c2_data);
+       db8500_add_i2c3(&u8500_i2c3_data);
+}
 
-/*
- * Nomadik SKE keypad
- */
-#define ROW_PIN_I0      164
-#define ROW_PIN_I1      163
-#define ROW_PIN_I2      162
-#define ROW_PIN_I3      161
-#define ROW_PIN_I4      156
-#define ROW_PIN_I5      155
-#define ROW_PIN_I6      154
-#define ROW_PIN_I7      153
-#define COL_PIN_O0      168
-#define COL_PIN_O1      167
-#define COL_PIN_O2      166
-#define COL_PIN_O3      165
-#define COL_PIN_O4      160
-#define COL_PIN_O5      159
-#define COL_PIN_O6      158
-#define COL_PIN_O7      157
-
-#define SKE_KPD_MAX_ROWS        8
-#define SKE_KPD_MAX_COLS        8
-
-static int ske_kp_rows[] = {
-       ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
-       ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
+/* add any platform devices here - TODO */
+static struct platform_device *platform_devs[] __initdata = {
 };
 
-/*
- * ske_set_gpio_row: request and set gpio rows
- */
-static int ske_set_gpio_row(int gpio)
+static void __init mop500_spi_init(void)
 {
-       int ret;
-
-       ret = gpio_request(gpio, "ske-kp");
-       if (ret < 0) {
-               pr_err("ske_set_gpio_row: gpio request failed\n");
-               return ret;
-       }
-
-       ret = gpio_direction_output(gpio, 1);
-       if (ret < 0) {
-               pr_err("ske_set_gpio_row: gpio direction failed\n");
-               gpio_free(gpio);
-       }
-
-       return ret;
+       db8500_add_ssp0(&ssp0_platform_data);
 }
 
-/*
- * ske_kp_init - enable the gpio configuration
- */
-static int ske_kp_init(void)
+static void __init mop500_uart_init(void)
 {
-       int ret, i;
-
-       for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
-               ret = ske_set_gpio_row(ske_kp_rows[i]);
-               if (ret < 0) {
-                       pr_err("ske_kp_init: failed init\n");
-                       return ret;
-               }
-       }
-
-       return 0;
+       db8500_add_uart0();
+       db8500_add_uart1();
+       db8500_add_uart2();
 }
 
-static struct ske_keypad_platform_data ske_keypad_board = {
-       .init           = ske_kp_init,
-       .keymap_data    = &ux500_keymap_data,
-       .no_autorepeat  = true,
-       .krow           = SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
-       .kcol           = SKE_KPD_MAX_COLS,
-       .debounce_ms    = 40,                   /* in millsecs */
-};
-
-
-
-/* add any platform devices here - TODO */
-static struct platform_device *platform_devs[] __initdata = {
-       &u8500_i2c0_device,
-       &ux500_i2c1_device,
-       &ux500_i2c2_device,
-       &ux500_i2c3_device,
-       &ux500_ske_keypad_device,
-};
-
 static void __init u8500_init_machine(void)
 {
-       int i;
-
        u8500_init_devices();
 
        nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins));
 
-       u8500_i2c0_device.dev.platform_data = &u8500_i2c0_data;
-       ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
-       ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data;
-       ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data;
-       ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board;
-
-       u8500_ssp0_device.dev.platform_data = &ssp0_platform_data;
-
-       /* Register the active AMBA devices on this board */
-       for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
-               amba_device_register(amba_devs[i], &iomem_resource);
-
        platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
+       mop500_i2c_init();
        mop500_sdi_init();
+       mop500_spi_init();
+       mop500_uart_init();
+
+       mop500_keypad_init();
+
+       platform_device_register(&ab8500_device);
 
-       /* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */
-       if (cpu_is_u8500ed() || cpu_is_u8500v10())
-               spi_register_board_info(ab8500_spi_devices,
-                       ARRAY_SIZE(ab8500_spi_devices));
-       else /* If HW is v.1.1 or later use I2C to access AB8500 */
-               platform_device_register(&ab8500_device);
+       i2c_register_board_info(0, mop500_i2c0_devices,
+                               ARRAY_SIZE(mop500_i2c0_devices));
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
index 2d240322fa6f77117720e6fbebfb84bd94ee9e6e..3104ae2a02c2d45d8f8578638babaf20d0b132b8 100644 (file)
@@ -7,6 +7,15 @@
 #ifndef __BOARD_MOP500_H
 #define __BOARD_MOP500_H
 
+#define MOP500_EGPIO(x)                        (NOMADIK_NR_GPIO + (x))
+
+/* GPIOs on the TC35892 expander */
+#define GPIO_SDMMC_CD                  MOP500_EGPIO(3)
+#define GPIO_SDMMC_EN                  MOP500_EGPIO(17)
+#define GPIO_SDMMC_1V8_3V_SEL          MOP500_EGPIO(18)
+
 extern void mop500_sdi_init(void);
+extern void mop500_sdi_tc35892_init(void);
+extern void mop500_keypad_init(void);
 
 #endif
diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c
new file mode 100644 (file)
index 0000000..54712ac
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Hanumath Prasad <ulf.hansson@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/amba/mmci.h>
+#include <linux/mmc/host.h>
+#include <linux/gpio.h>
+
+#include <plat/pincfg.h>
+#include <mach/db5500-regs.h>
+#include <plat/ste_dma40.h>
+
+#include "pins-db5500.h"
+#include "devices-db5500.h"
+#include "ste-dma40-db5500.h"
+
+static pin_cfg_t u5500_sdi_pins[] = {
+       /* SDI0 (POP eMMC) */
+       GPIO5_MC0_DAT0          | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO6_MC0_DAT1          | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO7_MC0_DAT2          | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO8_MC0_DAT3          | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO9_MC0_DAT4          | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO10_MC0_DAT5         | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO11_MC0_DAT6         | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO12_MC0_DAT7         | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO13_MC0_CMD          | PIN_DIR_INPUT | PIN_PULL_UP,
+       GPIO14_MC0_CLK          | PIN_DIR_OUTPUT | PIN_VAL_LOW,
+};
+
+static struct mmci_platform_data u5500_sdi0_data = {
+       .ocr_mask       = MMC_VDD_165_195,
+       .f_max          = 50000000,
+       .capabilities   = MMC_CAP_4_BIT_DATA |
+                               MMC_CAP_8_BIT_DATA |
+                               MMC_CAP_MMC_HIGHSPEED,
+       .gpio_cd        = -1,
+       .gpio_wp        = -1,
+};
+
+void __init u5500_sdi_init(void)
+{
+       nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins));
+
+       db5500_add_sdi0(&u5500_sdi0_data);
+}
index 1ca094a45e71df68ebd123ecd03092f8eedb89f1..39d370c1f3b4270b96630ea8eb382738a3f487f5 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/gpio.h>
+#include <linux/irq.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/devices.h>
 #include <mach/setup.h>
 
-static struct amba_device *amba_board_devs[] __initdata = {
-       &ux500_uart0_device,
-       &ux500_uart1_device,
-       &ux500_uart2_device,
-};
+#include "devices-db5500.h"
+
+static void __init u5500_uart_init(void)
+{
+       db5500_add_uart0();
+       db5500_add_uart1();
+       db5500_add_uart2();
+}
 
 static void __init u5500_init_machine(void)
 {
        u5500_init_devices();
 
-       amba_add_devices(amba_board_devs, ARRAY_SIZE(amba_board_devs));
+       u5500_sdi_init();
+       u5500_uart_init();
 }
 
-MACHINE_START(U8500, "ST-Ericsson U5500 Platform")
+MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
        .boot_params    = 0x00000100,
        .map_io         = u5500_map_io,
        .init_irq       = ux500_init_irq,
index 1675047daf20f74f5f00a1a7e88feab2e5c4f281..912d1cc18c5767affee605e444becf3f07775c4b 100644 (file)
 #include <mach/hardware.h>
 #include "clock.h"
 
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>     /* for copy_from_user */
+static LIST_HEAD(clk_list);
+#endif
+
 #define PRCC_PCKEN             0x00
 #define PRCC_PCKDIS            0x04
 #define PRCC_KCKEN             0x08
@@ -133,7 +139,7 @@ static unsigned long clk_mtu_get_rate(struct clk *clk)
 {
        void __iomem *addr = __io_address(UX500_PRCMU_BASE)
                + PRCM_TCR;
-       u32 tcr = readl(addr);
+       u32 tcr;
        int mtu = (int) clk->data;
        /*
         * One of these is selected eventually
@@ -144,6 +150,14 @@ static unsigned long clk_mtu_get_rate(struct clk *clk)
        unsigned long mturate;
        unsigned long retclk;
 
+       /*
+        * On a startup, always conifgure the TCR to the doze mode;
+        * bootloaders do it for us. Do this in the kernel too.
+        */
+       writel(PRCM_TCR_DOZE_MODE, addr);
+
+       tcr = readl(addr);
+
        /* Get the rate from the parent as a default */
        if (clk->parent_periph)
                mturate = clk_get_rate(clk->parent_periph);
@@ -153,45 +167,6 @@ static unsigned long clk_mtu_get_rate(struct clk *clk)
                /* We need to be connected SOMEWHERE */
                BUG();
 
-       /*
-        * Are we in doze mode?
-        * In this mode the parent peripheral or the fixed 32768 Hz
-        * clock is fed into the block.
-        */
-       if (!(tcr & PRCM_TCR_DOZE_MODE)) {
-               /*
-                * Here we're using the clock input from the APE ULP
-                * clock domain. But first: are the timers stopped?
-                */
-               if (tcr & PRCM_TCR_STOPPED) {
-                       clk32k = 0;
-                       mturate = 0;
-               } else {
-                       /* Else default mode: 0 and 2.4 MHz */
-                       clk32k = 0;
-                       if (cpu_is_u5500())
-                               /* DB5500 divides by 8 */
-                               mturate /= 8;
-                       else if (cpu_is_u8500ed()) {
-                               /*
-                                * This clocking setting must not be used
-                                * in the ED chip, it is simply not
-                                * connected anywhere!
-                                */
-                               mturate = 0;
-                               BUG();
-                       } else
-                               /*
-                                * In this mode the ulp38m4 clock is divided
-                                * by a factor 16, on the DB8500 typically
-                                * 38400000 / 16 ~ 2.4 MHz.
-                                * TODO: Replace the constant with a reference
-                                * to the ULP source once this is modeled.
-                                */
-                               mturate = 38400000 / 16;
-               }
-       }
-
        /* Return the clock selected for this MTU */
        if (tcr & (1 << mtu))
                retclk = clk32k;
@@ -317,6 +292,7 @@ static struct clkops clk_prcc_ops = {
 };
 
 static struct clk clk_32khz = {
+       .name =  "clk_32khz",
        .rate = 32000,
 };
 
@@ -366,94 +342,96 @@ static DEFINE_PRCMU_CLK(uiccclk,  0x4, 1, UICCCLK); /* v1 */
  */
 
 /* Peripheral Cluster #1 */
-static DEFINE_PRCC_CLK(1, i2c4,        10, 9, &clk_i2cclk);
+static DEFINE_PRCC_CLK(1, i2c4,                10, 9, &clk_i2cclk);
 static DEFINE_PRCC_CLK(1, gpio0,       9, -1, NULL);
-static DEFINE_PRCC_CLK(1, slimbus0,    8,  8, &clk_slimclk);
-static DEFINE_PRCC_CLK(1, spi3_ed,     7,  7, NULL);
-static DEFINE_PRCC_CLK(1, spi3_v1,     7, -1, NULL);
-static DEFINE_PRCC_CLK(1, i2c2,        6,  6, &clk_i2cclk);
+static DEFINE_PRCC_CLK(1, slimbus0,    8,  8, &clk_slimclk);
+static DEFINE_PRCC_CLK(1, spi3_ed,     7,  7, NULL);
+static DEFINE_PRCC_CLK(1, spi3_v1,     7, -1, NULL);
+static DEFINE_PRCC_CLK(1, i2c2,                6,  6, &clk_i2cclk);
 static DEFINE_PRCC_CLK(1, sdi0,                5,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(1, msp1_ed,     4,  4, &clk_msp02clk);
-static DEFINE_PRCC_CLK(1, msp1_v1,     4,  4, &clk_msp1clk);
-static DEFINE_PRCC_CLK(1, msp0,        3,  3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(1, i2c1,        2,  2, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, uart1,       1,  1, &clk_uartclk);
-static DEFINE_PRCC_CLK(1, uart0,       0,  0, &clk_uartclk);
+static DEFINE_PRCC_CLK(1, msp1_ed,     4,  4, &clk_msp02clk);
+static DEFINE_PRCC_CLK(1, msp1_v1,     4,  4, &clk_msp1clk);
+static DEFINE_PRCC_CLK(1, msp0,                3,  3, &clk_msp02clk);
+static DEFINE_PRCC_CLK(1, i2c1,                2,  2, &clk_i2cclk);
+static DEFINE_PRCC_CLK(1, uart1,       1,  1, &clk_uartclk);
+static DEFINE_PRCC_CLK(1, uart0,       0,  0, &clk_uartclk);
 
 /* Peripheral Cluster #2 */
 
 static DEFINE_PRCC_CLK(2, gpio1_ed,    12, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssitx_ed,    11, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssirx_ed,    10, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi0_ed,      9, -1, NULL);
-static DEFINE_PRCC_CLK(2, sdi3_ed,      8,  6, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, sdi1_ed,      7,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, msp2_ed,      6,  4, &clk_msp02clk);
-static DEFINE_PRCC_CLK(2, sdi4_ed,      4,  2, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, ssitx_ed,    11, -1, NULL);
+static DEFINE_PRCC_CLK(2, ssirx_ed,    10, -1, NULL);
+static DEFINE_PRCC_CLK(2, spi0_ed,      9, -1, NULL);
+static DEFINE_PRCC_CLK(2, sdi3_ed,      8,  6, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, sdi1_ed,      7,  5, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, msp2_ed,      6,  4, &clk_msp02clk);
+static DEFINE_PRCC_CLK(2, sdi4_ed,      4,  2, &clk_sdmmcclk);
 static DEFINE_PRCC_CLK(2, pwl_ed,       3,  1, NULL);
-static DEFINE_PRCC_CLK(2, spi1_ed,      2, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi2_ed,      1, -1, NULL);
-static DEFINE_PRCC_CLK(2, i2c3_ed,      0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(2, spi1_ed,      2, -1, NULL);
+static DEFINE_PRCC_CLK(2, spi2_ed,      1, -1, NULL);
+static DEFINE_PRCC_CLK(2, i2c3_ed,      0,  0, &clk_i2cclk);
 
 static DEFINE_PRCC_CLK(2, gpio1_v1,    11, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssitx_v1,    10,  7, NULL);
-static DEFINE_PRCC_CLK(2, ssirx_v1,     9,  6, NULL);
-static DEFINE_PRCC_CLK(2, spi0_v1,      8, -1, NULL);
-static DEFINE_PRCC_CLK(2, sdi3_v1,      7,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, sdi1_v1,      6,  4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, msp2_v1,      5,  3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(2, sdi4_v1,      4,  2, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, ssitx_v1,    10,  7, NULL);
+static DEFINE_PRCC_CLK(2, ssirx_v1,     9,  6, NULL);
+static DEFINE_PRCC_CLK(2, spi0_v1,      8, -1, NULL);
+static DEFINE_PRCC_CLK(2, sdi3_v1,      7,  5, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, sdi1_v1,      6,  4, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(2, msp2_v1,      5,  3, &clk_msp02clk);
+static DEFINE_PRCC_CLK(2, sdi4_v1,      4,  2, &clk_sdmmcclk);
 static DEFINE_PRCC_CLK(2, pwl_v1,       3,  1, NULL);
-static DEFINE_PRCC_CLK(2, spi1_v1,      2, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi2_v1,      1, -1, NULL);
-static DEFINE_PRCC_CLK(2, i2c3_v1,      0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(2, spi1_v1,      2, -1, NULL);
+static DEFINE_PRCC_CLK(2, spi2_v1,      1, -1, NULL);
+static DEFINE_PRCC_CLK(2, i2c3_v1,      0,  0, &clk_i2cclk);
 
 /* Peripheral Cluster #3 */
-static DEFINE_PRCC_CLK(3, gpio2,       8, -1, NULL);
-static DEFINE_PRCC_CLK(3, sdi5,        7,  7, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, uart2,       6,  6, &clk_uartclk);
-static DEFINE_PRCC_CLK(3, ske,                 5,  5, &clk_32khz);
-static DEFINE_PRCC_CLK(3, sdi2,        4,  4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, i2c0,        3,  3, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp1_ed,     2,  2, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp0_ed,     1,  1, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp1_v1,     2,  2, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, ssp0_v1,     1,  1, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, fsmc,        0, -1, NULL);
+static DEFINE_PRCC_CLK(3, gpio2,       8, -1, NULL);
+static DEFINE_PRCC_CLK(3, sdi5,                7,  7, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(3, uart2,       6,  6, &clk_uartclk);
+static DEFINE_PRCC_CLK(3, ske,         5,  5, &clk_32khz);
+static DEFINE_PRCC_CLK(3, sdi2,                4,  4, &clk_sdmmcclk);
+static DEFINE_PRCC_CLK(3, i2c0,                3,  3, &clk_i2cclk);
+static DEFINE_PRCC_CLK(3, ssp1_ed,     2,  2, &clk_i2cclk);
+static DEFINE_PRCC_CLK(3, ssp0_ed,     1,  1, &clk_i2cclk);
+static DEFINE_PRCC_CLK(3, ssp1_v1,     2,  2, &clk_sspclk);
+static DEFINE_PRCC_CLK(3, ssp0_v1,     1,  1, &clk_sspclk);
+static DEFINE_PRCC_CLK(3, fsmc,                0, -1, NULL);
 
 /* Peripheral Cluster #4 is in the always on domain */
 
 /* Peripheral Cluster #5 */
-static DEFINE_PRCC_CLK(5, gpio3,       1, -1, NULL);
-static DEFINE_PRCC_CLK(5, usb_ed,      0,  0, &clk_i2cclk);
-static DEFINE_PRCC_CLK(5, usb_v1,      0,  0, NULL);
+static DEFINE_PRCC_CLK(5, gpio3,       1, -1, NULL);
+static DEFINE_PRCC_CLK(5, usb_ed,      0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(5, usb_v1,      0,  0, NULL);
 
 /* Peripheral Cluster #6 */
 
 /* MTU ID in data */
 static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
 static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(6, cfgreg_v1,   6,  6, NULL);
-static DEFINE_PRCC_CLK(6, dmc_ed,      6,  6, NULL);
-static DEFINE_PRCC_CLK(6, hash1,       5, -1, NULL);
-static DEFINE_PRCC_CLK(6, unipro_v1,   4,  1, &clk_uniproclk);
-static DEFINE_PRCC_CLK(6, cryp1_ed,    4, -1, NULL);
-static DEFINE_PRCC_CLK(6, pka,                 3, -1, NULL);
-static DEFINE_PRCC_CLK(6, hash0,       2, -1, NULL);
-static DEFINE_PRCC_CLK(6, cryp0,       1, -1, NULL);
-static DEFINE_PRCC_CLK(6, rng_ed,      0,  0, &clk_i2cclk);
-static DEFINE_PRCC_CLK(6, rng_v1,      0,  0, &clk_rngclk);
+static DEFINE_PRCC_CLK(6, cfgreg_v1,   6,  6, NULL);
+static DEFINE_PRCC_CLK(6, dmc_ed,      6,  6, NULL);
+static DEFINE_PRCC_CLK(6, hash1,       5, -1, NULL);
+static DEFINE_PRCC_CLK(6, unipro_v1,   4,  1, &clk_uniproclk);
+static DEFINE_PRCC_CLK(6, cryp1_ed,    4, -1, NULL);
+static DEFINE_PRCC_CLK(6, pka,         3, -1, NULL);
+static DEFINE_PRCC_CLK(6, hash0,       2, -1, NULL);
+static DEFINE_PRCC_CLK(6, cryp0,       1, -1, NULL);
+static DEFINE_PRCC_CLK(6, rng_ed,      0,  0, &clk_i2cclk);
+static DEFINE_PRCC_CLK(6, rng_v1,      0,  0, &clk_rngclk);
 
 /* Peripheral Cluster #7 */
 
-static DEFINE_PRCC_CLK(7, tzpc0_ed,    4, -1, NULL);
+static DEFINE_PRCC_CLK(7, tzpc0_ed,    4, -1, NULL);
 /* MTU ID in data */
 static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
 static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(7, wdg_ed,      1, -1, NULL);
-static DEFINE_PRCC_CLK(7, cfgreg_ed,   0, -1, NULL);
+static DEFINE_PRCC_CLK(7, wdg_ed,      1, -1, NULL);
+static DEFINE_PRCC_CLK(7, cfgreg_ed,   0, -1, NULL);
 
-static struct clk clk_dummy_apb_pclk;
+static struct clk clk_dummy_apb_pclk = {
+       .name = "apb_pclk",
+};
 
 static struct clk_lookup u8500_common_clks[] = {
        CLK(dummy_apb_pclk, NULL,       "apb_pclk"),
@@ -554,7 +532,7 @@ static struct clk_lookup u8500_ed_clks[] = {
 
 static struct clk_lookup u8500_v1_clks[] = {
        /* Peripheral Cluster #1 */
-       CLK(i2c4,       "nmk-i2c.4",    NULL),
+       CLK(i2c4,       "nmk-i2c.4",    NULL),
        CLK(spi3_v1,    "spi3",         NULL),
        CLK(msp1_v1,    "msp1",         NULL),
 
@@ -599,6 +577,183 @@ static struct clk_lookup u8500_v1_clks[] = {
        CLK(uiccclk,    "uicc",         NULL),
 };
 
+#ifdef CONFIG_DEBUG_FS
+/*
+ *     debugfs support to trace clock tree hierarchy and attributes with
+ *     powerdebug
+ */
+static struct dentry *clk_debugfs_root;
+
+void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
+{
+       while (num--) {
+               /* Check that the clock has not been already registered */
+               if (!(cl->clk->list.prev != cl->clk->list.next))
+                       list_add_tail(&cl->clk->list, &clk_list);
+
+               cl++;
+       }
+}
+
+static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
+                                                 size_t size, loff_t *off)
+{
+       struct clk *clk = file->f_dentry->d_inode->i_private;
+       char cusecount[128];
+       unsigned int len;
+
+       len = sprintf(cusecount, "%u\n", clk->enabled);
+       return simple_read_from_buffer(buf, size, off, cusecount, len);
+}
+
+static ssize_t rate_dbg_read(struct file *file, char __user *buf,
+                                         size_t size, loff_t *off)
+{
+       struct clk *clk = file->f_dentry->d_inode->i_private;
+       char crate[128];
+       unsigned int rate;
+       unsigned int len;
+
+       rate = clk_get_rate(clk);
+       len = sprintf(crate, "%u\n", rate);
+       return simple_read_from_buffer(buf, size, off, crate, len);
+}
+
+static const struct file_operations usecount_fops = {
+       .read = usecount_dbg_read,
+};
+
+static const struct file_operations set_rate_fops = {
+       .read = rate_dbg_read,
+};
+
+static struct dentry *clk_debugfs_register_dir(struct clk *c,
+                                               struct dentry *p_dentry)
+{
+       struct dentry *d, *clk_d, *child, *child_tmp;
+       char s[255];
+       char *p = s;
+
+       if (c->name == NULL)
+               p += sprintf(p, "BUG");
+       else
+               p += sprintf(p, "%s", c->name);
+
+       clk_d = debugfs_create_dir(s, p_dentry);
+       if (!clk_d)
+               return NULL;
+
+       d = debugfs_create_file("usecount", S_IRUGO,
+                               clk_d, c, &usecount_fops);
+       if (!d)
+               goto err_out;
+       d = debugfs_create_file("rate", S_IRUGO,
+                               clk_d, c, &set_rate_fops);
+       if (!d)
+               goto err_out;
+       /*
+        * TODO : not currently available in ux500
+        * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
+        * if (!d)
+        *      goto err_out;
+        */
+
+       return clk_d;
+
+err_out:
+       d = clk_d;
+       list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+               debugfs_remove(child);
+       debugfs_remove(clk_d);
+       return NULL;
+}
+
+static void clk_debugfs_remove_dir(struct dentry *cdentry)
+{
+       struct dentry *d, *child, *child_tmp;
+
+       d = cdentry;
+       list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+               debugfs_remove(child);
+       debugfs_remove(cdentry);
+       return ;
+}
+
+static int clk_debugfs_register_one(struct clk *c)
+{
+       struct clk *pa = c->parent_periph;
+       struct clk *bpa = c->parent_cluster;
+
+       if (!(bpa && !pa)) {
+               c->dent = clk_debugfs_register_dir(c,
+                               pa ? pa->dent : clk_debugfs_root);
+               if (!c->dent)
+                       return -ENOMEM;
+       }
+
+       if (bpa) {
+               c->dent_bus = clk_debugfs_register_dir(c,
+                               bpa->dent_bus ? bpa->dent_bus : bpa->dent);
+               if ((!c->dent_bus) &&  (c->dent)) {
+                       clk_debugfs_remove_dir(c->dent);
+                       c->dent = NULL;
+                       return -ENOMEM;
+               }
+       }
+       return 0;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+       int err;
+       struct clk *pa = c->parent_periph;
+       struct clk *bpa = c->parent_cluster;
+
+       if (pa && (!pa->dent && !pa->dent_bus)) {
+               err = clk_debugfs_register(pa);
+               if (err)
+                       return err;
+       }
+
+       if (bpa && (!bpa->dent && !bpa->dent_bus)) {
+               err = clk_debugfs_register(bpa);
+               if (err)
+                       return err;
+       }
+
+       if ((!c->dent) && (!c->dent_bus)) {
+               err = clk_debugfs_register_one(c);
+               if (err)
+                       return err;
+       }
+       return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+       struct clk *c;
+       struct dentry *d;
+       int err;
+
+       d = debugfs_create_dir("clock", NULL);
+       if (!d)
+               return -ENOMEM;
+       clk_debugfs_root = d;
+
+       list_for_each_entry(c, &clk_list, list) {
+               err = clk_debugfs_register(c);
+               if (err)
+                       goto err_out;
+       }
+       return 0;
+err_out:
+       debugfs_remove_recursive(clk_debugfs_root);
+       return err;
+}
+
+late_initcall(clk_debugfs_init);
+#endif /* defined(CONFIG_DEBUG_FS) */
+
 int __init clk_init(void)
 {
        if (cpu_is_u8500ed()) {
@@ -609,7 +764,8 @@ int __init clk_init(void)
                /* Clock tree for U5500 not implemented yet */
                clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
                clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
-               clk_per6clk.rate = 26000000;
+               clk_uartclk.rate = 36360000;
+               clk_sdmmcclk.rate = 99900000;
        }
 
        clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
@@ -618,5 +774,12 @@ int __init clk_init(void)
        else
                clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
 
+#ifdef CONFIG_DEBUG_FS
+       clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
+       if (cpu_is_u8500ed())
+               clk_debugfs_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
+       else
+               clk_debugfs_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
+#endif
        return 0;
 }
index a058025015273f81b20cc6cd34a46255811e744a..074490705229a73a987b380441ad569d083d8ef1 100644 (file)
@@ -90,6 +90,10 @@ struct clk {
 
        struct clk              *parent_cluster;
        struct clk              *parent_periph;
+#if defined(CONFIG_DEBUG_FS)
+       struct dentry           *dent;          /* For visible tree hierarchy */
+       struct dentry           *dent_bus;      /* For visible tree hierarchy */
+#endif
 };
 
 #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg)                \
index 2f87075e9d6f02a21a08c28f7c4ae3a04e69257e..acc841e48de40b2f16e2a4f4145b11edf2e72697 100644 (file)
@@ -8,14 +8,19 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 
 #include <asm/mach/map.h>
 
+#include <plat/gpio.h>
+
 #include <mach/hardware.h>
 #include <mach/devices.h>
 #include <mach/setup.h>
 #include <mach/irqs.h>
 
+#include "devices-db5500.h"
+
 static struct map_desc u5500_io_desc[] __initdata = {
        __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
        __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K),
@@ -110,19 +115,32 @@ static struct platform_device mbox2_device = {
 };
 
 static struct platform_device *u5500_platform_devs[] __initdata = {
-       &u5500_gpio_devs[0],
-       &u5500_gpio_devs[1],
-       &u5500_gpio_devs[2],
-       &u5500_gpio_devs[3],
-       &u5500_gpio_devs[4],
-       &u5500_gpio_devs[5],
-       &u5500_gpio_devs[6],
-       &u5500_gpio_devs[7],
        &mbox0_device,
        &mbox1_device,
        &mbox2_device,
 };
 
+static resource_size_t __initdata db5500_gpio_base[] = {
+       U5500_GPIOBANK0_BASE,
+       U5500_GPIOBANK1_BASE,
+       U5500_GPIOBANK2_BASE,
+       U5500_GPIOBANK3_BASE,
+       U5500_GPIOBANK4_BASE,
+       U5500_GPIOBANK5_BASE,
+       U5500_GPIOBANK6_BASE,
+       U5500_GPIOBANK7_BASE,
+};
+
+static void __init db5500_add_gpios(void)
+{
+       struct nmk_gpio_platform_data pdata = {
+               /* No custom data yet */
+       };
+
+       dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base),
+                        IRQ_DB5500_GPIO0, &pdata);
+}
+
 void __init u5500_map_io(void)
 {
        ux500_map_io();
@@ -132,7 +150,9 @@ void __init u5500_map_io(void)
 
 void __init u5500_init_devices(void)
 {
-       ux500_init_devices();
+       db5500_add_gpios();
+       db5500_dma_init();
+       db5500_add_rtc();
 
        platform_add_devices(u5500_platform_devs,
                             ARRAY_SIZE(u5500_platform_devs));
index 4acab7544b3c1e95ea9a9f2c73cf0f1ffd34847d..c0f34a404c532c03a3a11d263afd26a1a5c2910b 100644 (file)
 #include <mach/setup.h>
 #include <mach/devices.h>
 
+#include "devices-db8500.h"
+
 static struct platform_device *platform_devs[] __initdata = {
-       &u8500_gpio_devs[0],
-       &u8500_gpio_devs[1],
-       &u8500_gpio_devs[2],
-       &u8500_gpio_devs[3],
-       &u8500_gpio_devs[4],
-       &u8500_gpio_devs[5],
-       &u8500_gpio_devs[6],
-       &u8500_gpio_devs[7],
-       &u8500_gpio_devs[8],
        &u8500_dma40_device,
 };
 
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
-       __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
        __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
@@ -46,13 +38,18 @@ static struct map_desc u8500_io_desc[] __initdata = {
        __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
 };
 
-static struct map_desc u8500ed_io_desc[] __initdata = {
+static struct map_desc u8500_ed_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K),
        __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K),
 };
 
-static struct map_desc u8500v1_io_desc[] __initdata = {
+static struct map_desc u8500_v1_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
+       __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K),
+};
+
+static struct map_desc u8500_v2_io_desc[] __initdata = {
+       __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
 };
 
 /*
@@ -125,14 +122,38 @@ void __init u8500_map_io(void)
        iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
 
        if (cpu_is_u8500ed())
-               iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
-       else
-               iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
+               iotable_init(u8500_ed_io_desc, ARRAY_SIZE(u8500_ed_io_desc));
+       else if (cpu_is_u8500v1())
+               iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc));
+       else if (cpu_is_u8500v2())
+               iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc));
 
        /* Read out the ASIC ID as early as we can */
        get_db8500_asic_id();
 }
 
+static resource_size_t __initdata db8500_gpio_base[] = {
+       U8500_GPIOBANK0_BASE,
+       U8500_GPIOBANK1_BASE,
+       U8500_GPIOBANK2_BASE,
+       U8500_GPIOBANK3_BASE,
+       U8500_GPIOBANK4_BASE,
+       U8500_GPIOBANK5_BASE,
+       U8500_GPIOBANK6_BASE,
+       U8500_GPIOBANK7_BASE,
+       U8500_GPIOBANK8_BASE,
+};
+
+static void __init db8500_add_gpios(void)
+{
+       struct nmk_gpio_platform_data pdata = {
+               /* No custom data yet */
+       };
+
+       dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base),
+                        IRQ_DB8500_GPIO0, &pdata);
+}
+
 /*
  * This function is called from the board init
  */
@@ -152,12 +173,13 @@ void __init u8500_init_devices(void)
        else
                pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
 
-       ux500_init_devices();
-
        if (cpu_is_u8500ed())
                dma40_u8500ed_fixup();
 
-       /* Register the platform devices */
+       db8500_add_rtc();
+       db8500_add_gpios();
+
+       platform_device_register_simple("cpufreq-u8500", -1, NULL, 0);
        platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
        return ;
index 608a1372b172267170aaab6ecb2e0276fd5d49be..a3700bc374d379c6e4fbfc57aef7d5c8b92c0803 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/platform_device.h>
-#include <linux/amba/bus.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 
@@ -20,6 +19,7 @@
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/prcmu.h>
 
 #include "clock.h"
 
@@ -45,20 +45,11 @@ static struct map_desc ux500_io_desc[] __initdata = {
        __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K),
 };
 
-static struct amba_device *ux500_amba_devs[] __initdata = {
-       &ux500_pl031_device,
-};
-
 void __init ux500_map_io(void)
 {
        iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc));
 }
 
-void __init ux500_init_devices(void)
-{
-       amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs));
-}
-
 void __init ux500_init_irq(void)
 {
        gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
@@ -68,6 +59,8 @@ void __init ux500_init_irq(void)
         * Init clocks here so that they are available for system timer
         * initialization.
         */
+       if (cpu_is_u8500())
+               prcmu_early_init();
        clk_init();
 }
 
diff --git a/arch/arm/mach-ux500/cpufreq.c b/arch/arm/mach-ux500/cpufreq.c
new file mode 100644 (file)
index 0000000..5c5b747
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * CPU frequency scaling for u8500
+ * Inspired by linux/arch/arm/mach-davinci/cpufreq.c
+ *
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Martin Persson <martin.persson@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu.h>
+#include <mach/prcmu-defs.h>
+
+#define DRIVER_NAME "cpufreq-u8500"
+#define CPUFREQ_NAME "u8500"
+
+static struct device *dev;
+
+static struct cpufreq_frequency_table freq_table[] = {
+       [0] = {
+               .index = 0,
+               .frequency = 200000,
+       },
+       [1] = {
+               .index = 1,
+               .frequency = 300000,
+       },
+       [2] = {
+               .index = 2,
+               .frequency = 600000,
+       },
+       [3] = {
+               /* Used for CPU_OPP_MAX, if available */
+               .index = 3,
+               .frequency = CPUFREQ_TABLE_END,
+       },
+       [4] = {
+               .index = 4,
+               .frequency = CPUFREQ_TABLE_END,
+       },
+};
+
+static enum prcmu_cpu_opp index2opp[] = {
+       CPU_OPP_EXT_CLK,
+       CPU_OPP_50,
+       CPU_OPP_100,
+       CPU_OPP_MAX
+};
+
+static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static int u8500_cpufreq_target(struct cpufreq_policy *policy,
+                               unsigned int target_freq,
+                               unsigned int relation)
+{
+       struct cpufreq_freqs freqs;
+       unsigned int index;
+       int ret = 0;
+
+       /*
+        * Ensure desired rate is within allowed range.  Some govenors
+        * (ondemand) will just pass target_freq=0 to get the minimum.
+        */
+       if (target_freq < policy->cpuinfo.min_freq)
+               target_freq = policy->cpuinfo.min_freq;
+       if (target_freq > policy->cpuinfo.max_freq)
+               target_freq = policy->cpuinfo.max_freq;
+
+       ret = cpufreq_frequency_table_target(policy, freq_table,
+                                            target_freq, relation, &index);
+       if (ret < 0) {
+               dev_err(dev, "Could not look up next frequency\n");
+               return ret;
+       }
+
+       freqs.old = policy->cur;
+       freqs.new = freq_table[index].frequency;
+       freqs.cpu = policy->cpu;
+
+       if (freqs.old == freqs.new) {
+               dev_dbg(dev, "Current and target frequencies are equal\n");
+               return 0;
+       }
+
+       dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new);
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+       ret = prcmu_set_cpu_opp(index2opp[index]);
+       if (ret < 0) {
+               dev_err(dev, "Failed to set OPP level\n");
+               return ret;
+       }
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       return ret;
+}
+
+static unsigned int u8500_cpufreq_getspeed(unsigned int cpu)
+{
+       int i;
+
+       for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++)
+               ;
+       return freq_table[i].frequency;
+}
+
+static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy)
+{
+       int res;
+
+       BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table));
+
+       if (cpu_is_u8500v2()) {
+               freq_table[1].frequency = 400000;
+               freq_table[2].frequency = 800000;
+               if (prcmu_has_arm_maxopp())
+                       freq_table[3].frequency = 1000000;
+       }
+
+       /* get policy fields based on the table */
+       res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       if (!res)
+               cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+       else {
+               dev_err(dev, "u8500-cpufreq : Failed to read policy table\n");
+               return res;
+       }
+
+       policy->min = policy->cpuinfo.min_freq;
+       policy->max = policy->cpuinfo.max_freq;
+       policy->cur = u8500_cpufreq_getspeed(policy->cpu);
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       /*
+        * FIXME : Need to take time measurement across the target()
+        *         function with no/some/all drivers in the notification
+        *         list.
+        */
+       policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */
+
+       /* policy sharing between dual CPUs */
+       cpumask_copy(policy->cpus, &cpu_present_map);
+
+       policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+
+       return res;
+}
+
+static struct freq_attr *u8500_cpufreq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+static int u8500_cpu_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       return 0;
+}
+
+static struct cpufreq_driver u8500_driver = {
+       .owner = THIS_MODULE,
+       .flags = CPUFREQ_STICKY,
+       .verify = u8500_cpufreq_verify_speed,
+       .target = u8500_cpufreq_target,
+       .get = u8500_cpufreq_getspeed,
+       .init = u8500_cpu_init,
+       .exit = u8500_cpu_exit,
+       .name = CPUFREQ_NAME,
+       .attr = u8500_cpufreq_attr,
+};
+
+static int __init u8500_cpufreq_probe(struct platform_device *pdev)
+{
+       dev = &pdev->dev;
+       return cpufreq_register_driver(&u8500_driver);
+}
+
+static int __exit u8500_cpufreq_remove(struct platform_device *pdev)
+{
+       return cpufreq_unregister_driver(&u8500_driver);
+}
+
+static struct platform_driver u8500_cpufreq_driver = {
+       .driver = {
+               .name    = DRIVER_NAME,
+               .owner   = THIS_MODULE,
+       },
+       .remove = __exit_p(u8500_cpufreq_remove),
+};
+
+static int __init u8500_cpufreq_init(void)
+{
+       return platform_driver_probe(&u8500_cpufreq_driver,
+                                    &u8500_cpufreq_probe);
+}
+
+device_initcall(u8500_cpufreq_init);
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
new file mode 100644 (file)
index 0000000..fe69f5f
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+
+#include <plat/gpio.h>
+
+#include <mach/hardware.h>
+
+#include "devices-common.h"
+
+struct amba_device *
+dbx500_add_amba_device(const char *name, resource_size_t base,
+                      int irq, void *pdata, unsigned int periphid)
+{
+       struct amba_device *dev;
+       int ret;
+
+       dev = kzalloc(sizeof *dev, GFP_KERNEL);
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       dev->dev.init_name = name;
+
+       dev->res.start = base;
+       dev->res.end = base + SZ_4K - 1;
+       dev->res.flags = IORESOURCE_MEM;
+
+       dev->dma_mask = DMA_BIT_MASK(32);
+       dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+       dev->irq[0] = irq;
+       dev->irq[1] = NO_IRQ;
+
+       dev->periphid = periphid;
+
+       dev->dev.platform_data = pdata;
+
+       ret = amba_device_register(dev, &iomem_resource);
+       if (ret) {
+               kfree(dev);
+               return ERR_PTR(ret);
+       }
+
+       return dev;
+}
+
+static struct platform_device *
+dbx500_add_platform_device(const char *name, int id, void *pdata,
+                          struct resource *res, int resnum)
+{
+       struct platform_device *dev;
+       int ret;
+
+       dev = platform_device_alloc(name, id);
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+
+       ret = platform_device_add_resources(dev, res, resnum);
+       if (ret)
+               goto out_free;
+
+       dev->dev.platform_data = pdata;
+
+       ret = platform_device_add(dev);
+       if (ret)
+               goto out_free;
+
+       return dev;
+
+out_free:
+       platform_device_put(dev);
+       return ERR_PTR(ret);
+}
+
+struct platform_device *
+dbx500_add_platform_device_4k1irq(const char *name, int id,
+                                 resource_size_t base,
+                                 int irq, void *pdata)
+{
+       struct resource resources[] = {
+               [0] = {
+                       .start  = base,
+                       .end    = base + SZ_4K - 1,
+                       .flags  = IORESOURCE_MEM,
+               },
+               [1] = {
+                       .start  = irq,
+                       .end    = irq,
+                       .flags  = IORESOURCE_IRQ,
+               }
+       };
+
+       return dbx500_add_platform_device(name, id, pdata, resources,
+                                         ARRAY_SIZE(resources));
+}
+
+static struct platform_device *
+dbx500_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));
+}
+
+void dbx500_add_gpios(resource_size_t *base, int num, int irq,
+                     struct nmk_gpio_platform_data *pdata)
+{
+       int first = 0;
+       int i;
+
+       for (i = 0; i < num; i++, first += 32, irq++) {
+               pdata->first_gpio = first;
+               pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
+
+               dbx500_add_gpio(i, base[i], irq, pdata);
+       }
+}
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
new file mode 100644 (file)
index 0000000..cbadc11
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_COMMON_H
+#define __DEVICES_COMMON_H
+
+extern struct amba_device *
+dbx500_add_amba_device(const char *name, resource_size_t base,
+                      int irq, void *pdata, unsigned int periphid);
+
+extern struct platform_device *
+dbx500_add_platform_device_4k1irq(const char *name, int id,
+                                 resource_size_t base,
+                                 int irq, void *pdata);
+
+struct spi_master_cntlr;
+
+static inline struct amba_device *
+dbx500_add_msp_spi(const char *name, resource_size_t base, int irq,
+                  struct spi_master_cntlr *pdata)
+{
+       return dbx500_add_amba_device(name, base, irq, pdata, 0);
+}
+
+static inline struct amba_device *
+dbx500_add_spi(const char *name, resource_size_t base, int irq,
+                                  struct spi_master_cntlr *pdata)
+{
+       return dbx500_add_amba_device(name, base, irq, pdata, 0);
+}
+
+struct mmci_platform_data;
+
+static inline struct amba_device *
+dbx500_add_sdi(const char *name, resource_size_t base, int irq,
+              struct mmci_platform_data *pdata)
+{
+       return dbx500_add_amba_device(name, base, irq, pdata, 0);
+}
+
+static inline struct amba_device *
+dbx500_add_uart(const char *name, resource_size_t base, int irq)
+{
+       return dbx500_add_amba_device(name, base, irq, NULL, 0);
+}
+
+struct nmk_i2c_controller;
+
+static inline struct platform_device *
+dbx500_add_i2c(int id, resource_size_t base, int irq,
+              struct nmk_i2c_controller *pdata)
+{
+       return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq,
+                                                pdata);
+}
+
+struct msp_i2s_platform_data;
+
+static inline struct platform_device *
+dbx500_add_msp_i2s(int id, resource_size_t base, int irq,
+                  struct msp_i2s_platform_data *pdata)
+{
+       return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq,
+                                                pdata);
+}
+
+static inline struct amba_device *
+dbx500_add_rtc(resource_size_t base, int irq)
+{
+       return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0);
+}
+
+struct nmk_gpio_platform_data;
+
+void dbx500_add_gpios(resource_size_t *base, int num, int irq,
+                     struct nmk_gpio_platform_data *pdata);
+
+#endif
diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c
deleted file mode 100644 (file)
index 33e5b56..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <mach/devices.h>
-
-static struct nmk_gpio_platform_data u5500_gpio_data[] = {
-       GPIO_DATA("GPIO-0-31", 0),
-       GPIO_DATA("GPIO-32-63", 32), /* 36..63 not routed to pin */
-       GPIO_DATA("GPIO-64-95", 64), /* 83..95 not routed to pin */
-       GPIO_DATA("GPIO-96-127", 96), /* 102..127 not routed to pin */
-       GPIO_DATA("GPIO-128-159", 128), /* 149..159 not routed to pin */
-       GPIO_DATA("GPIO-160-191", 160),
-       GPIO_DATA("GPIO-192-223", 192),
-       GPIO_DATA("GPIO-224-255", 224), /* 228..255 not routed to pin */
-};
-
-static struct resource u5500_gpio_resources[] = {
-       GPIO_RESOURCE(0),
-       GPIO_RESOURCE(1),
-       GPIO_RESOURCE(2),
-       GPIO_RESOURCE(3),
-       GPIO_RESOURCE(4),
-       GPIO_RESOURCE(5),
-       GPIO_RESOURCE(6),
-       GPIO_RESOURCE(7),
-};
-
-struct platform_device u5500_gpio_devs[] = {
-       GPIO_DEVICE(0),
-       GPIO_DEVICE(1),
-       GPIO_DEVICE(2),
-       GPIO_DEVICE(3),
-       GPIO_DEVICE(4),
-       GPIO_DEVICE(5),
-       GPIO_DEVICE(6),
-       GPIO_DEVICE(7),
-};
diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h
new file mode 100644 (file)
index 0000000..c8d7901
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_DB5500_H
+#define __DEVICES_DB5500_H
+
+#include "devices-common.h"
+
+#define db5500_add_i2c1(pdata) \
+       dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata)
+#define db5500_add_i2c2(pdata) \
+       dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata)
+#define db5500_add_i2c3(pdata) \
+       dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata)
+
+#define db5500_add_msp0_i2s(pdata) \
+       dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_i2s(pdata) \
+       dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_i2s(pdata) \
+       dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+
+#define db5500_add_msp0_spi(pdata) \
+       dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_spi(pdata) \
+       dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_spi(pdata) \
+       dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+
+#define db5500_add_rtc() \
+       dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
+
+#define db5500_add_sdi0(pdata) \
+       dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata)
+#define db5500_add_sdi1(pdata) \
+       dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata)
+#define db5500_add_sdi2(pdata) \
+       dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata)
+#define db5500_add_sdi3(pdata) \
+       dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata)
+#define db5500_add_sdi4(pdata) \
+       dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata)
+
+#define db5500_add_spi0(pdata) \
+       dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata)
+#define db5500_add_spi1(pdata) \
+       dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata)
+#define db5500_add_spi2(pdata) \
+       dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata)
+#define db5500_add_spi3(pdata) \
+       dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata)
+
+#define db5500_add_uart0() \
+       dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0)
+#define db5500_add_uart1() \
+       dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1)
+#define db5500_add_uart2() \
+       dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2)
+#define db5500_add_uart3() \
+       dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3)
+
+#endif
index 4a94be3304b91a852a7732d5b6e8eeda5b37866d..23c695d54977d7a551d06fdb529f28d4195c4efe 100644 (file)
 
 #include "ste-dma40-db8500.h"
 
-static struct nmk_gpio_platform_data u8500_gpio_data[] = {
-       GPIO_DATA("GPIO-0-31", 0),
-       GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */
-       GPIO_DATA("GPIO-64-95", 64),
-       GPIO_DATA("GPIO-96-127", 96), /* 98..127 not routed to pin */
-       GPIO_DATA("GPIO-128-159", 128),
-       GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */
-       GPIO_DATA("GPIO-192-223", 192),
-       GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */
-       GPIO_DATA("GPIO-256-288", 256), /* 268..288 not routed to pin */
-};
-
-static struct resource u8500_gpio_resources[] = {
-       GPIO_RESOURCE(0),
-       GPIO_RESOURCE(1),
-       GPIO_RESOURCE(2),
-       GPIO_RESOURCE(3),
-       GPIO_RESOURCE(4),
-       GPIO_RESOURCE(5),
-       GPIO_RESOURCE(6),
-       GPIO_RESOURCE(7),
-       GPIO_RESOURCE(8),
-};
-
-struct platform_device u8500_gpio_devs[] = {
-       GPIO_DEVICE(0),
-       GPIO_DEVICE(1),
-       GPIO_DEVICE(2),
-       GPIO_DEVICE(3),
-       GPIO_DEVICE(4),
-       GPIO_DEVICE(5),
-       GPIO_DEVICE(6),
-       GPIO_DEVICE(7),
-       GPIO_DEVICE(8),
-};
-
-struct amba_device u8500_ssp0_device = {
-       .dev = {
-               .coherent_dma_mask = ~0,
-               .init_name = "ssp0",
-       },
-       .res = {
-               .start = U8500_SSP0_BASE,
-               .end   = U8500_SSP0_BASE + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       .irq = {IRQ_DB8500_SSP0, NO_IRQ },
-       /* ST-Ericsson modified id */
-       .periphid = SSP_PER_ID,
-};
-
-static struct resource u8500_i2c0_resources[] = {
-       [0] = {
-               .start  = U8500_I2C0_BASE,
-               .end    = U8500_I2C0_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_DB8500_I2C0,
-               .end    = IRQ_DB8500_I2C0,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-struct platform_device u8500_i2c0_device = {
-       .name           = "nmk-i2c",
-       .id             = 0,
-       .resource       = u8500_i2c0_resources,
-       .num_resources  = ARRAY_SIZE(u8500_i2c0_resources),
-};
-
-static struct resource u8500_i2c4_resources[] = {
-       [0] = {
-               .start  = U8500_I2C4_BASE,
-               .end    = U8500_I2C4_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_DB8500_I2C4,
-               .end    = IRQ_DB8500_I2C4,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-struct platform_device u8500_i2c4_device = {
-       .name           = "nmk-i2c",
-       .id             = 4,
-       .resource       = u8500_i2c4_resources,
-       .num_resources  = ARRAY_SIZE(u8500_i2c4_resources),
-};
-
-/*
- * SD/MMC
- */
-
-struct amba_device u8500_sdi0_device = {
-       .dev            = {
-               .init_name = "sdi0",
-       },
-       .res            = {
-               .start  = U8500_SDI0_BASE,
-               .end    = U8500_SDI0_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       .irq            = {IRQ_DB8500_SDMMC0, NO_IRQ},
-};
-
-struct amba_device u8500_sdi1_device = {
-       .dev            = {
-               .init_name = "sdi1",
-       },
-       .res            = {
-               .start  = U8500_SDI1_BASE,
-               .end    = U8500_SDI1_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       .irq            = {IRQ_DB8500_SDMMC1, NO_IRQ},
-};
-
-struct amba_device u8500_sdi2_device = {
-       .dev            = {
-               .init_name = "sdi2",
-       },
-       .res            = {
-               .start  = U8500_SDI2_BASE,
-               .end    = U8500_SDI2_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       .irq            = {IRQ_DB8500_SDMMC2, NO_IRQ},
-};
-
-struct amba_device u8500_sdi3_device = {
-       .dev            = {
-               .init_name = "sdi3",
-       },
-       .res            = {
-               .start  = U8500_SDI3_BASE,
-               .end    = U8500_SDI3_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       .irq            = {IRQ_DB8500_SDMMC3, NO_IRQ},
-};
-
-struct amba_device u8500_sdi4_device = {
-       .dev            = {
-               .init_name = "sdi4",
-       },
-       .res            = {
-               .start  = U8500_SDI4_BASE,
-               .end    = U8500_SDI4_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       .irq            = {IRQ_DB8500_SDMMC4, NO_IRQ},
-};
-
-struct amba_device u8500_sdi5_device = {
-       .dev            = {
-               .init_name = "sdi5",
-       },
-       .res            = {
-               .start  = U8500_SDI5_BASE,
-               .end    = U8500_SDI5_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       .irq            = {IRQ_DB8500_SDMMC5, NO_IRQ},
-};
-
 static struct resource dma40_resources[] = {
        [0] = {
                .start = U8500_DMA_BASE,
@@ -295,7 +128,7 @@ struct resource keypad_resources[] = {
        },
 };
 
-struct platform_device ux500_ske_keypad_device = {
+struct platform_device u8500_ske_keypad_device = {
        .name = "nmk-ske-keypad",
        .id = -1,
        .num_resources = ARRAY_SIZE(keypad_resources),
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
new file mode 100644 (file)
index 0000000..3a770c7
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_DB8500_H
+#define __DEVICES_DB8500_H
+
+#include "devices-common.h"
+
+struct ske_keypad_platform_data;
+struct pl022_ssp_controller;
+
+static inline struct platform_device *
+db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata)
+{
+       return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1,
+                                                U8500_SKE_BASE,
+                                                IRQ_DB8500_KB, pdata);
+}
+
+static inline struct amba_device *
+db8500_add_ssp(const char *name, resource_size_t base, int irq,
+              struct pl022_ssp_controller *pdata)
+{
+       return dbx500_add_amba_device(name, base, irq, pdata, SSP_PER_ID);
+}
+
+
+#define db8500_add_i2c0(pdata) \
+       dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
+#define db8500_add_i2c1(pdata) \
+       dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata)
+#define db8500_add_i2c2(pdata) \
+       dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata)
+#define db8500_add_i2c3(pdata) \
+       dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata)
+#define db8500_add_i2c4(pdata) \
+       dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
+
+#define db8500_add_msp0_i2s(pdata) \
+       dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_i2s(pdata) \
+       dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_i2s(pdata) \
+       dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_i2s(pdata) \
+       dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_msp0_spi(pdata) \
+       dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_spi(pdata) \
+       dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_spi(pdata) \
+       dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_spi(pdata) \
+       dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_rtc() \
+       dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
+
+#define db8500_add_sdi0(pdata) \
+       dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata)
+#define db8500_add_sdi1(pdata) \
+       dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata)
+#define db8500_add_sdi2(pdata) \
+       dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata)
+#define db8500_add_sdi3(pdata) \
+       dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata)
+#define db8500_add_sdi4(pdata) \
+       dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata)
+#define db8500_add_sdi5(pdata) \
+       dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata)
+
+#define db8500_add_ssp0(pdata) \
+       db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata)
+#define db8500_add_ssp1(pdata) \
+       db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata)
+
+#define db8500_add_spi0(pdata) \
+       dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata)
+#define db8500_add_spi1(pdata) \
+       dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata)
+#define db8500_add_spi2(pdata) \
+       dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata)
+#define db8500_add_spi3(pdata) \
+       dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata)
+
+#define db8500_add_uart0() \
+       dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0)
+#define db8500_add_uart1() \
+       dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1)
+#define db8500_add_uart2() \
+       dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2)
+
+#endif
index 8a268893cb7fb8315c51732cce455b6a5fe6d4c9..ea0a2f92ca70875ff0716722f35fbd3dc45a91dd 100644 (file)
 #include <mach/hardware.h>
 #include <mach/setup.h>
 
-#define __MEM_4K_RESOURCE(x) \
-       .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
-
-struct amba_device ux500_pl031_device = {
-       .dev = {
-               .init_name = "pl031",
-       },
-       .res = {
-               .start  = UX500_RTC_BASE,
-               .end    = UX500_RTC_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       .irq = {IRQ_RTC_RTT, NO_IRQ},
-};
-
-struct amba_device ux500_uart0_device = {
-       .dev = { .init_name = "uart0" },
-       __MEM_4K_RESOURCE(UX500_UART0_BASE),
-       .irq = {IRQ_UART0, NO_IRQ},
-};
-
-struct amba_device ux500_uart1_device = {
-       .dev = { .init_name = "uart1" },
-       __MEM_4K_RESOURCE(UX500_UART1_BASE),
-       .irq = {IRQ_UART1, NO_IRQ},
-};
-
-struct amba_device ux500_uart2_device = {
-       .dev = { .init_name = "uart2" },
-       __MEM_4K_RESOURCE(UX500_UART2_BASE),
-       .irq = {IRQ_UART2, NO_IRQ},
-};
-
-#define UX500_I2C_RESOURCES(id, size)                          \
-static struct resource ux500_i2c##id##_resources[] = {         \
-       [0] = {                                                 \
-               .start  = UX500_I2C##id##_BASE,                 \
-               .end    = UX500_I2C##id##_BASE + size - 1,      \
-               .flags  = IORESOURCE_MEM,                       \
-       },                                                      \
-       [1] = {                                                 \
-               .start  = IRQ_I2C##id,                          \
-               .end    = IRQ_I2C##id,                          \
-               .flags  = IORESOURCE_IRQ                        \
-       }                                                       \
-}
-
-UX500_I2C_RESOURCES(1, SZ_4K);
-UX500_I2C_RESOURCES(2, SZ_4K);
-UX500_I2C_RESOURCES(3, SZ_4K);
-
-#define UX500_I2C_PDEVICE(cid)                                 \
-struct platform_device ux500_i2c##cid##_device = {             \
-       .name           = "nmk-i2c",                            \
-       .id             = cid,                                  \
-       .num_resources  = 2,                                    \
-       .resource       = ux500_i2c##cid##_resources,           \
-}
-
-UX500_I2C_PDEVICE(1);
-UX500_I2C_PDEVICE(2);
-UX500_I2C_PDEVICE(3);
-
 void __init amba_add_devices(struct amba_device *devs[], int num)
 {
        int i;
diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c
new file mode 100644 (file)
index 0000000..32a061f
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabinv.vincent@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <plat/ste_dma40.h>
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+#include "ste-dma40-db5500.h"
+
+static struct resource dma40_resources[] = {
+       [0] = {
+               .start = U5500_DMA_BASE,
+               .end   = U5500_DMA_BASE + SZ_4K - 1,
+               .flags = IORESOURCE_MEM,
+               .name  = "base",
+       },
+       [1] = {
+               .start = U5500_DMA_LCPA_BASE,
+               .end   = U5500_DMA_LCPA_BASE + 2 * SZ_1K - 1,
+               .flags = IORESOURCE_MEM,
+               .name  = "lcpa",
+       },
+       [2] = {
+               .start = IRQ_DB5500_DMA,
+               .end   = IRQ_DB5500_DMA,
+               .flags = IORESOURCE_IRQ
+       }
+};
+
+/* Default configuration for physical memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
+       .mode = STEDMA40_MODE_PHYSICAL,
+       .dir = STEDMA40_MEM_TO_MEM,
+
+       .src_info.data_width = STEDMA40_BYTE_WIDTH,
+       .src_info.psize = STEDMA40_PSIZE_PHY_1,
+       .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+       .dst_info.data_width = STEDMA40_BYTE_WIDTH,
+       .dst_info.psize = STEDMA40_PSIZE_PHY_1,
+       .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+};
+
+/* Default configuration for logical memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_log = {
+       .dir = STEDMA40_MEM_TO_MEM,
+
+       .src_info.data_width = STEDMA40_BYTE_WIDTH,
+       .src_info.psize = STEDMA40_PSIZE_LOG_1,
+       .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+       .dst_info.data_width = STEDMA40_BYTE_WIDTH,
+       .dst_info.psize = STEDMA40_PSIZE_LOG_1,
+       .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+};
+
+/*
+ * Mapping between soruce event lines and physical device address This was
+ * created assuming that the event line is tied to a device and therefore the
+ * address is constant, however this is not true for at least USB, and the
+ * values are just placeholders for USB.  This table is preserved and used for
+ * now.
+ */
+static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = {
+       [DB5500_DMA_DEV24_SDMMC0_RX] = -1,
+};
+
+/* Mapping between destination event lines and physical device address */
+static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = {
+       [DB5500_DMA_DEV24_SDMMC0_TX] = -1,
+};
+
+static int dma40_memcpy_event[] = {
+       DB5500_DMA_MEMCPY_TX_1,
+       DB5500_DMA_MEMCPY_TX_2,
+       DB5500_DMA_MEMCPY_TX_3,
+       DB5500_DMA_MEMCPY_TX_4,
+       DB5500_DMA_MEMCPY_TX_5,
+};
+
+static struct stedma40_platform_data dma40_plat_data = {
+       .dev_len                = ARRAY_SIZE(dma40_rx_map),
+       .dev_rx                 = dma40_rx_map,
+       .dev_tx                 = dma40_tx_map,
+       .memcpy                 = dma40_memcpy_event,
+       .memcpy_len             = ARRAY_SIZE(dma40_memcpy_event),
+       .memcpy_conf_phy        = &dma40_memcpy_conf_phy,
+       .memcpy_conf_log        = &dma40_memcpy_conf_log,
+       .disabled_channels      = {-1},
+};
+
+static struct platform_device dma40_device = {
+       .dev = {
+               .platform_data = &dma40_plat_data,
+       },
+       .name           = "dma40",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(dma40_resources),
+       .resource       = dma40_resources
+};
+
+void __init db5500_dma_init(void)
+{
+       int ret;
+
+       ret = platform_device_register(&dma40_device);
+       if (ret)
+               dev_err(&dma40_device.dev, "unable to register device: %d\n", ret);
+
+}
index 3eafc0e24ba58d75671221a60bdcafbb68388a27..bd88c1e74060740158c95ab0c427d40265717694 100644 (file)
 #define U5500_MBOX2_LOCAL_START        (U5500_MBOX_BASE + 0x20)
 #define U5500_MBOX2_LOCAL_END  (U5500_MBOX_BASE + 0x3F)
 
+#define U5500_ESRAM_BASE               0x40000000
+#define U5500_ESRAM_DMA_LCPA_OFFSET    0x10000
+#define U5500_DMA_LCPA_BASE    (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET)
+
 #endif
index f07d0986409d2341771a39e1298538d466192f36..0fefb34c11e4b89d7705051e3cb44c9d06fa4c3e 100644 (file)
@@ -92,7 +92,8 @@
 #define U8500_SCR_BASE         (U8500_PER4_BASE + 0x05000)
 #define U8500_DMC_BASE         (U8500_PER4_BASE + 0x06000)
 #define U8500_PRCMU_BASE       (U8500_PER4_BASE + 0x07000)
-#define U8500_PRCMU_TCDM_BASE  (U8500_PER4_BASE + 0x0f000)
+#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
+#define U8500_PRCMU_TCDM_BASE   (U8500_PER4_BASE + 0x68000)
 
 /* per3 base addresses */
 #define U8500_FSMC_BASE                (U8500_PER3_BASE + 0x0000)
index b91a4d1211a27997141a38055151c45e19698078..020b6369a30a4fb401af2cbd2316b72e003c63d7 100644 (file)
@@ -14,27 +14,10 @@ extern struct platform_device u5500_gpio_devs[];
 extern struct platform_device u8500_gpio_devs[];
 
 extern struct amba_device ux500_pl031_device;
-extern struct amba_device u8500_ssp0_device;
-extern struct amba_device ux500_uart0_device;
-extern struct amba_device ux500_uart1_device;
-extern struct amba_device ux500_uart2_device;
 
-extern struct platform_device ux500_i2c1_device;
-extern struct platform_device ux500_i2c2_device;
-extern struct platform_device ux500_i2c3_device;
-
-extern struct platform_device u8500_i2c0_device;
-extern struct platform_device u8500_i2c4_device;
 extern struct platform_device u8500_dma40_device;
 extern struct platform_device ux500_ske_keypad_device;
 
-extern struct amba_device u8500_sdi0_device;
-extern struct amba_device u8500_sdi1_device;
-extern struct amba_device u8500_sdi2_device;
-extern struct amba_device u8500_sdi3_device;
-extern struct amba_device u8500_sdi4_device;
-extern struct amba_device u8500_sdi5_device;
-
 void dma40_u8500ed_fixup(void);
 
 #endif
index d548a622e7d24eeb8f54cb5dcb03caa9268370e6..3c4cd31ad9f734a8b463ad4f2b24b50ef1c3836b 100644 (file)
@@ -9,42 +9,4 @@
 
 #include <plat/gpio.h>
 
-#define __GPIO_RESOURCE(soc, block)                                    \
-       {                                                               \
-               .start  = soc##_GPIOBANK##block##_BASE,                 \
-               .end    = soc##_GPIOBANK##block##_BASE + 127,           \
-               .flags  = IORESOURCE_MEM,                               \
-       },                                                              \
-       {                                                               \
-               .start  = IRQ_GPIO##block,                              \
-               .end    = IRQ_GPIO##block,                              \
-               .flags  = IORESOURCE_IRQ,                               \
-       }
-
-#define __GPIO_DEVICE(soc, block)                                      \
-       {                                                               \
-               .name           = "gpio",                               \
-               .id             = block,                                \
-               .num_resources  = 2,                                    \
-               .resource       = &soc##_gpio_resources[block * 2],     \
-               .dev = {                                                \
-                       .platform_data = &soc##_gpio_data[block],       \
-               },                                                      \
-       }
-
-#define GPIO_DATA(_name, first)                                                \
-       {                                                               \
-               .name           = _name,                                \
-               .first_gpio     = first,                                \
-               .first_irq      = NOMADIK_GPIO_TO_IRQ(first),           \
-       }
-
-#ifdef CONFIG_UX500_SOC_DB8500
-#define GPIO_RESOURCE(block)   __GPIO_RESOURCE(U8500, block)
-#define GPIO_DEVICE(block)     __GPIO_DEVICE(u8500, block)
-#elif defined(CONFIG_UX500_SOC_DB5500)
-#define GPIO_RESOURCE(block)   __GPIO_RESOURCE(U5500, block)
-#define GPIO_DEVICE(block)     __GPIO_DEVICE(u5500, block)
-#endif
-
 #endif /* __ASM_ARCH_GPIO_H */
index 32e883a8f2a22af6f122a9d529a6d85541d70b64..6295cc581355c97e926205a815e642ac5d924f34 100644 (file)
@@ -142,6 +142,8 @@ static inline bool cpu_is_u5500(void)
 #endif
 }
 
+#define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)
+
 #endif
 
 #endif                         /* __MACH_HARDWARE_H */
index cca4f705601e35ced0040a2177280569317e4019..7cdeb2af0ebb7691a395be014bd5a96be17691da 100644 (file)
@@ -8,12 +8,36 @@
 #ifndef __MACH_IRQS_BOARD_MOP500_H
 #define __MACH_IRQS_BOARD_MOP500_H
 
-#define AB8500_NR_IRQS                 104
+/* Number of AB8500 irqs is taken from header file */
+#include <linux/mfd/ab8500.h>
 
 #define MOP500_AB8500_IRQ_BASE         IRQ_BOARD_START
 #define MOP500_AB8500_IRQ_END          (MOP500_AB8500_IRQ_BASE \
                                         + AB8500_NR_IRQS)
-#define MOP500_IRQ_END                 MOP500_AB8500_IRQ_END
+
+/* TC35892 */
+#define TC35892_NR_INTERNAL_IRQS       8
+#define TC35892_INT_GPIO(x)            (TC35892_NR_INTERNAL_IRQS + (x))
+#define TC35892_NR_GPIOS               24
+#define TC35892_NR_IRQS                        TC35892_INT_GPIO(TC35892_NR_GPIOS)
+
+#define MOP500_EGPIO_NR_IRQS           TC35892_NR_IRQS
+
+#define MOP500_EGPIO_IRQ_BASE          MOP500_AB8500_IRQ_END
+#define MOP500_EGPIO_IRQ_END           (MOP500_EGPIO_IRQ_BASE \
+                                        + MOP500_EGPIO_NR_IRQS)
+/* STMPE1601 irqs */
+#define STMPE_NR_INTERNAL_IRQS          9
+#define STMPE_INT_GPIO(x)               (STMPE_NR_INTERNAL_IRQS + (x))
+#define STMPE_NR_GPIOS                  24
+#define STMPE_NR_IRQS                   STMPE_INT_GPIO(STMPE_NR_GPIOS)
+
+#define MOP500_STMPE1601_IRQBASE        MOP500_EGPIO_IRQ_END
+#define MOP500_STMPE1601_IRQ(x)         (MOP500_STMPE1601_IRQBASE + (x))
+
+#define MOP500_NR_IRQS          MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
+
+#define MOP500_IRQ_END          MOP500_NR_IRQS
 
 #if MOP500_IRQ_END > IRQ_BOARD_END
 #undef IRQ_BOARD_END
index 693aa57de88d995375db54b3d9cefbffc25679c1..880ae45bc2352b6d5452690f24a713f748b47fbe 100644 (file)
 
 /* Interrupt numbers generic for shared peripheral */
 #define IRQ_MTU0               (IRQ_SHPI_START + 4)
-#define IRQ_SPI2               (IRQ_SHPI_START + 6)
-#define IRQ_SPI0               (IRQ_SHPI_START + 8)
-#define IRQ_UART0              (IRQ_SHPI_START + 11)
-#define IRQ_I2C3               (IRQ_SHPI_START + 12)
-#define IRQ_SSP0               (IRQ_SHPI_START + 14)
-#define IRQ_MTU1               (IRQ_SHPI_START + 17)
-#define IRQ_RTC_RTT            (IRQ_SHPI_START + 18)
-#define IRQ_UART1              (IRQ_SHPI_START + 19)
-#define IRQ_I2C0               (IRQ_SHPI_START + 21)
-#define IRQ_I2C1               (IRQ_SHPI_START + 22)
-#define IRQ_USBOTG             (IRQ_SHPI_START + 23)
-#define IRQ_DMA                        (IRQ_SHPI_START + 25)
-#define IRQ_UART2              (IRQ_SHPI_START + 26)
-#define IRQ_HSIR_EXCEP         (IRQ_SHPI_START + 29)
-#define IRQ_MSP0               (IRQ_SHPI_START + 31)
-#define IRQ_HSIR_CH0_OVRRUN    (IRQ_SHPI_START + 32)
-#define IRQ_HSIR_CH1_OVRRUN    (IRQ_SHPI_START + 33)
-#define IRQ_HSIR_CH2_OVRRUN    (IRQ_SHPI_START + 34)
-#define IRQ_HSIR_CH3_OVRRUN    (IRQ_SHPI_START + 35)
-#define IRQ_AB8500             (IRQ_SHPI_START + 40)
-#define IRQ_PRCMU               (IRQ_SHPI_START + 47)
-#define IRQ_DISP               (IRQ_SHPI_START + 48)
-#define IRQ_SiPI3              (IRQ_SHPI_START + 49)
-#define IRQ_I2C4               (IRQ_SHPI_START + 51)
-#define IRQ_SSP1               (IRQ_SHPI_START + 52)
-#define IRQ_I2C2               (IRQ_SHPI_START + 55)
-#define IRQ_SDMMC0             (IRQ_SHPI_START + 60)
-#define IRQ_MSP1               (IRQ_SHPI_START + 62)
-#define IRQ_SPI1               (IRQ_SHPI_START + 96)
-#define IRQ_MSP2               (IRQ_SHPI_START + 98)
-#define IRQ_SDMMC4             (IRQ_SHPI_START + 99)
-#define IRQ_HSIRD0             (IRQ_SHPI_START + 104)
-#define IRQ_HSIRD1             (IRQ_SHPI_START + 105)
-#define IRQ_HSITD0             (IRQ_SHPI_START + 106)
-#define IRQ_HSITD1             (IRQ_SHPI_START + 107)
-#define IRQ_GPIO0              (IRQ_SHPI_START + 119)
-#define IRQ_GPIO1              (IRQ_SHPI_START + 120)
-#define IRQ_GPIO2              (IRQ_SHPI_START + 121)
-#define IRQ_GPIO3              (IRQ_SHPI_START + 122)
-#define IRQ_GPIO4              (IRQ_SHPI_START + 123)
-#define IRQ_GPIO5              (IRQ_SHPI_START + 124)
-#define IRQ_GPIO6              (IRQ_SHPI_START + 125)
-#define IRQ_GPIO7              (IRQ_SHPI_START + 126)
-#define IRQ_GPIO8              (IRQ_SHPI_START + 127)
 
 /* There are 128 shared peripheral interrupts assigned to
  * INTID[160:32]. The first 32 interrupts are reserved.
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-defs.h b/arch/arm/mach-ux500/include/mach/prcmu-defs.h
new file mode 100644 (file)
index 0000000..848ba64
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Martin Persson <martin.persson@stericsson.com>
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCM Unit definitions
+ */
+
+#ifndef __MACH_PRCMU_DEFS_H
+#define __MACH_PRCMU_DEFS_H
+
+enum prcmu_cpu_opp {
+       CPU_OPP_INIT      = 0x00,
+       CPU_OPP_NO_CHANGE = 0x01,
+       CPU_OPP_100       = 0x02,
+       CPU_OPP_50        = 0x03,
+       CPU_OPP_MAX       = 0x04,
+       CPU_OPP_EXT_CLK   = 0x07
+};
+enum prcmu_ape_opp {
+       APE_OPP_NO_CHANGE = 0x00,
+       APE_OPP_100       = 0x02,
+       APE_OPP_50        = 0x03,
+};
+
+#endif /* __MACH_PRCMU_DEFS_H */
index 8885f39a6421ca3e36d807e84835b44c8cb6fd15..455467e887915d628cd13ea416e47fc5d86ebdc6 100644 (file)
@@ -1,10 +1,15 @@
 /*
- * Copyright (c) 2009 ST-Ericsson SA
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
  *
- * 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.
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCM Unit registers
  */
+
 #ifndef __MACH_PRCMU_REGS_H
 #define __MACH_PRCMU_REGS_H
 
@@ -88,4 +93,4 @@
 /* Miscellaneous unit registers */
 #define PRCM_DSI_SW_RESET          (_PRCMU_BASE + 0x324)
 
-#endif /* __MACH_PRCMU__REGS_H */
+#endif /* __MACH_PRCMU_REGS_H */
index 549843ff6dbeecb72fb51ecebcb4f051cb38b1f7..c49e456162efdb8c208b73dc7e143017b8bdb0b5 100644 (file)
@@ -2,14 +2,27 @@
  * Copyright (C) STMicroelectronics 2009
  * Copyright (C) ST-Ericsson SA 2010
  *
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ *
  * License Terms: GNU General Public License v2
  *
- * PRCMU f/w APIs
+ * PRCM Unit f/w API
  */
 #ifndef __MACH_PRCMU_H
 #define __MACH_PRCMU_H
+#include <mach/prcmu-defs.h>
 
+void __init prcmu_early_init(void);
 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_set_ape_opp(enum prcmu_ape_opp opp);
+int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp);
+int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
+                          enum prcmu_cpu_opp cpu_opp);
+int prcmu_get_ape_opp(void);
+int prcmu_get_cpu_opp(void);
+bool prcmu_has_arm_maxopp(void);
 
 #endif /* __MACH_PRCMU_H */
index 54bbe648bf583575d390866d6b405e58a899abec..469877e0de900b54eb040b6b0099250e0b56d43c 100644 (file)
@@ -18,14 +18,19 @@ extern void __init ux500_map_io(void);
 extern void __init u5500_map_io(void);
 extern void __init u8500_map_io(void);
 
-extern void __init ux500_init_devices(void);
 extern void __init u5500_init_devices(void);
 extern void __init u8500_init_devices(void);
 
 extern void __init ux500_init_irq(void);
+
+extern void __init u5500_sdi_init(void);
+
+extern void __init db5500_dma_init(void);
+
 /* We re-use nomadik_timer for this platform */
 extern void nmdk_timer_init(void);
 
+struct amba_device;
 extern void __init amba_add_devices(struct amba_device *devs[], int num);
 
 struct sys_timer;
index 0271ca0a83df86c4fb43eb37b3c93754414d706d..9a6614c6808ecdc1d6101a2c01ce0b306c45caa1 100644 (file)
 #define __ASM_ARCH_UNCOMPRESS_H
 
 #include <asm/setup.h>
+#include <asm/mach-types.h>
 #include <linux/io.h>
+#include <linux/amba/serial.h>
 #include <mach/hardware.h>
 
-#define U8500_UART_DR          0x80007000
-#define U8500_UART_LCRH                0x8000702c
-#define U8500_UART_CR          0x80007030
-#define U8500_UART_FR          0x80007018
+static u32 ux500_uart_base;
 
 static void putc(const char c)
 {
        /* Do nothing if the UART is not enabled. */
-       if (!(__raw_readb(U8500_UART_CR) & 0x1))
+       if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
                return;
 
        if (c == '\n')
                putc('\r');
 
-       while (__raw_readb(U8500_UART_FR) & (1 << 5))
+       while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 5))
                barrier();
-       __raw_writeb(c, U8500_UART_DR);
+       __raw_writeb(c, ux500_uart_base + UART01x_DR);
 }
 
 static void flush(void)
 {
-       if (!(__raw_readb(U8500_UART_CR) & 0x1))
+       if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
                return;
-       while (__raw_readb(U8500_UART_FR) & (1 << 3))
+       while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 3))
                barrier();
 }
 
 static inline void arch_decomp_setup(void)
 {
+       if (machine_is_u8500())
+               ux500_uart_base = U8500_UART2_BASE;
+       else if (machine_is_u5500())
+               ux500_uart_base = U5500_UART0_BASE;
+       else /* not much can be done to help here */
+               ux500_uart_base = U8500_UART2_BASE;
 }
 
 #define arch_decomp_wdog() /* nothing to do here */
similarity index 99%
rename from arch/arm/mach-ux500/mbox.c
rename to arch/arm/mach-ux500/mbox-db5500.c
index 63435389c5444dc61651ff7f1b9460d215a6ce88..cbf15718fc3cb231354ea97da836bb34bebb55b3 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/completion.h>
-#include <mach/mbox.h>
+#include <mach/mbox-db5500.h>
 
 #define MBOX_NAME "mbox"
 
index 9e4c678de78593a248c9010a4eb8e0edcb4cb4dc..ade2e17f253c3665767d26d66c703ad9d1485bc1 100644 (file)
@@ -26,7 +26,7 @@
  * control for which core is the next to come out of the secondary
  * boot "holding pen"
  */
-volatile int __cpuinitdata pen_release = -1;
+volatile int pen_release = -1;
 
 static unsigned int __init get_core_count(void)
 {
index 293274d1342afd5a588f2e71edfad6d8035cc8e9..c522d26ef348fbc9eb779b58584c71f10805af2c 100644 (file)
@@ -1,10 +1,14 @@
 /*
- * Copyright (C) ST Ericsson SA 2010
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
  *
  * License Terms: GNU General Public License v2
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
  * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
  *
- * U8500 PRCMU driver.
+ * U8500 PRCM Unit interface driver
+ *
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/prcmu-regs.h>
+#include <mach/prcmu-defs.h>
+
+/* Global var to runtime determine TCDM base for v2 or v1 */
+static __iomem void *tcdm_base;
+
+#define _MBOX_HEADER           (tcdm_base + 0xFE8)
+#define MBOX_HEADER_REQ_MB0    (_MBOX_HEADER + 0x0)
+
+#define REQ_MB1 (tcdm_base + 0xFD0)
+#define REQ_MB5 (tcdm_base + 0xE44)
 
-#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE)
+#define REQ_MB1_ARMOPP         (REQ_MB1 + 0x0)
+#define REQ_MB1_APEOPP         (REQ_MB1 + 0x1)
+#define REQ_MB1_BOOSTOPP       (REQ_MB1 + 0x2)
 
-#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44)
-#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4)
+#define ACK_MB1 (tcdm_base + 0xE04)
+#define ACK_MB5 (tcdm_base + 0xDF4)
+
+#define ACK_MB1_CURR_ARMOPP            (ACK_MB1 + 0x0)
+#define ACK_MB1_CURR_APEOPP            (ACK_MB1 + 0x1)
 
 #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
 #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
 #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
 #define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
 
-#define I2C_WRITE(slave) ((slave) << 1)
-#define I2C_READ(slave) (((slave) << 1) | BIT(0))
+#define PRCM_AVS_VARM_MAX_OPP          (tcdm_base + 0x2E4)
+#define PRCM_AVS_ISMODEENABLE          7
+#define PRCM_AVS_ISMODEENABLE_MASK     (1 << PRCM_AVS_ISMODEENABLE)
+
+#define I2C_WRITE(slave) \
+       (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
+#define I2C_READ(slave) \
+       (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0))
 #define I2C_STOP_EN BIT(3)
 
+enum mb1_h {
+       MB1H_ARM_OPP = 1,
+       MB1H_APE_OPP,
+       MB1H_ARM_APE_OPP,
+};
+
+static struct {
+       struct mutex lock;
+       struct completion work;
+       struct {
+               u8 arm_opp;
+               u8 ape_opp;
+               u8 arm_status;
+               u8 ape_status;
+       } ack;
+} mb1_transfer;
+
 enum ack_mb5_status {
        I2C_WR_OK = 0x01,
        I2C_RD_OK = 0x02,
@@ -145,6 +187,104 @@ unlock_and_return:
 }
 EXPORT_SYMBOL(prcmu_abb_write);
 
+static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp,
+                           enum prcmu_cpu_opp cpu_opp)
+{
+       bool do_ape;
+       bool do_arm;
+       int err = 0;
+
+       do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP));
+       do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP));
+
+       mutex_lock(&mb1_transfer.lock);
+
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+               cpu_relax();
+
+       writeb(0, MBOX_HEADER_REQ_MB0);
+       writeb(cpu_opp, REQ_MB1_ARMOPP);
+       writeb(ape_opp, REQ_MB1_APEOPP);
+       writeb(0, REQ_MB1_BOOSTOPP);
+       writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
+       wait_for_completion(&mb1_transfer.work);
+       if ((do_ape) && (mb1_transfer.ack.ape_status != 0))
+               err = -EIO;
+       if ((do_arm) && (mb1_transfer.ack.arm_status != 0))
+               err = -EIO;
+
+       mutex_unlock(&mb1_transfer.lock);
+
+       return err;
+}
+
+/**
+ * prcmu_set_ape_opp() - Set the OPP of the APE.
+ * @opp:       The OPP to set.
+ *
+ * This function sets the OPP of the APE.
+ */
+int prcmu_set_ape_opp(enum prcmu_ape_opp opp)
+{
+       return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE);
+}
+EXPORT_SYMBOL(prcmu_set_ape_opp);
+
+/**
+ * prcmu_set_cpu_opp() - Set the OPP of the CPU.
+ * @opp:       The OPP to set.
+ *
+ * This function sets the OPP of the CPU.
+ */
+int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp)
+{
+       return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp);
+}
+EXPORT_SYMBOL(prcmu_set_cpu_opp);
+
+/**
+ * prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU.
+ * @ape_opp:   The APE OPP to set.
+ * @cpu_opp:   The CPU OPP to set.
+ *
+ * This function sets the OPPs of the APE and the CPU.
+ */
+int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
+                          enum prcmu_cpu_opp cpu_opp)
+{
+       return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp);
+}
+EXPORT_SYMBOL(prcmu_set_ape_cpu_opps);
+
+/**
+ * prcmu_get_ape_opp() - Get the OPP of the APE.
+ *
+ * This function gets the OPP of the APE.
+ */
+enum prcmu_ape_opp prcmu_get_ape_opp(void)
+{
+       return readb(ACK_MB1_CURR_APEOPP);
+}
+EXPORT_SYMBOL(prcmu_get_ape_opp);
+
+/**
+ * prcmu_get_cpu_opp() - Get the OPP of the CPU.
+ *
+ * This function gets the OPP of the CPU. The OPP is specified in %%.
+ * PRCMU_OPP_EXT is a special OPP value, not specified in %%.
+ */
+int prcmu_get_cpu_opp(void)
+{
+       return readb(ACK_MB1_CURR_ARMOPP);
+}
+EXPORT_SYMBOL(prcmu_get_cpu_opp);
+
+bool prcmu_has_arm_maxopp(void)
+{
+       return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK)
+               == PRCM_AVS_ISMODEENABLE_MASK;
+}
+
 static void read_mailbox_0(void)
 {
        writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
@@ -152,6 +292,9 @@ static void read_mailbox_0(void)
 
 static void read_mailbox_1(void)
 {
+       mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP);
+       mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP);
+       complete(&mb1_transfer.work);
        writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
 }
 
@@ -217,15 +360,35 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+void __init prcmu_early_init(void)
+{
+       if (cpu_is_u8500v11() || cpu_is_u8500ed()) {
+               tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1);
+       } else if (cpu_is_u8500v2()) {
+               tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
+       } else {
+               pr_err("prcmu: Unsupported chip version\n");
+               BUG();
+       }
+}
+
 static int __init prcmu_init(void)
 {
+       if (cpu_is_u8500ed()) {
+               pr_err("prcmu: Unsupported chip version\n");
+               return 0;
+       }
+
+       mutex_init(&mb1_transfer.lock);
+       init_completion(&mb1_transfer.work);
        mutex_init(&mb5_transfer.lock);
        init_completion(&mb5_transfer.work);
 
        /* Clean up the mailbox interrupts after pre-kernel code. */
        writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
 
-       return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL);
+       return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0,
+                          "prcmu", NULL);
 }
 
 arch_initcall(prcmu_init);
index 4414a01e1e8a392befa91d6da826f8ab1698223c..a099efed0e63540fce62f98aac4290da87156d8f 100644 (file)
@@ -382,6 +382,12 @@ config CPU_FEROCEON_OLD_ID
          for which the CPU ID is equal to the ARM926 ID.
          Relevant for Feroceon-1850 and early Feroceon-2850.
 
+# Marvell PJ4
+config CPU_PJ4
+       bool
+       select CPU_V7
+       select ARM_THUMBEE
+
 # ARMv6
 config CPU_V6
        bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_DOVE
@@ -789,7 +795,7 @@ config CACHE_PL310
 
 config CACHE_TAUROS2
        bool "Enable the Tauros2 L2 cache controller"
-       depends on (ARCH_DOVE || ARCH_MMP)
+       depends on (ARCH_DOVE || ARCH_MMP || CPU_PJ4)
        default y
        select OUTER_CACHE
        help
index 99fa688dfadd305113670aa48ea185a9899f8e5b..c96fa1b3f49f5d78b670289a1d8fc8ccf3b38b30 100644 (file)
@@ -203,6 +203,10 @@ ENTRY(v6_flush_kern_dcache_area)
  *     - end     - virtual end address of region
  */
 v6_dma_inv_range:
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrb    r2, [r0]                        @ read for ownership
+       strb    r2, [r0]                        @ write for ownership
+#endif
        tst     r0, #D_CACHE_LINE_SIZE - 1
        bic     r0, r0, #D_CACHE_LINE_SIZE - 1
 #ifdef HARVARD_CACHE
@@ -211,6 +215,10 @@ v6_dma_inv_range:
        mcrne   p15, 0, r0, c7, c11, 1          @ clean unified line
 #endif
        tst     r1, #D_CACHE_LINE_SIZE - 1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrneb  r2, [r1, #-1]                   @ read for ownership
+       strneb  r2, [r1, #-1]                   @ write for ownership
+#endif
        bic     r1, r1, #D_CACHE_LINE_SIZE - 1
 #ifdef HARVARD_CACHE
        mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D line
@@ -218,10 +226,6 @@ v6_dma_inv_range:
        mcrne   p15, 0, r1, c7, c15, 1          @ clean & invalidate unified line
 #endif
 1:
-#ifdef CONFIG_DMA_CACHE_RWFO
-       ldr     r2, [r0]                        @ read for ownership
-       str     r2, [r0]                        @ write for ownership
-#endif
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c6, 1           @ invalidate D line
 #else
@@ -229,6 +233,10 @@ v6_dma_inv_range:
 #endif
        add     r0, r0, #D_CACHE_LINE_SIZE
        cmp     r0, r1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrlo   r2, [r0]                        @ read for ownership
+       strlo   r2, [r0]                        @ write for ownership
+#endif
        blo     1b
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
@@ -263,12 +271,12 @@ v6_dma_clean_range:
  *     - end     - virtual end address of region
  */
 ENTRY(v6_dma_flush_range)
-       bic     r0, r0, #D_CACHE_LINE_SIZE - 1
-1:
 #ifdef CONFIG_DMA_CACHE_RWFO
-       ldr     r2, [r0]                        @ read for ownership
-       str     r2, [r0]                        @ write for ownership
+       ldrb    r2, [r0]                @ read for ownership
+       strb    r2, [r0]                @ write for ownership
 #endif
+       bic     r0, r0, #D_CACHE_LINE_SIZE - 1
+1:
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
 #else
@@ -276,6 +284,10 @@ ENTRY(v6_dma_flush_range)
 #endif
        add     r0, r0, #D_CACHE_LINE_SIZE
        cmp     r0, r1
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldrlob  r2, [r0]                        @ read for ownership
+       strlob  r2, [r0]                        @ write for ownership
+#endif
        blo     1b
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
index a3ebf7a4f49b2b404da115a58e7fdf6923792625..6136e68ce953d038ef0fa92b8211a3c477ef8e83 100644 (file)
@@ -173,15 +173,22 @@ ENTRY(v7_coherent_user_range)
  UNWIND(.fnstart               )
        dcache_line_size r2, r3
        sub     r3, r2, #1
-       bic     r0, r0, r3
+       bic     r12, r0, r3
 1:
- USER( mcr     p15, 0, r0, c7, c11, 1  )       @ clean D line to the point of unification
+ USER( mcr     p15, 0, r12, c7, c11, 1 )       @ clean D line to the point of unification
+       add     r12, r12, r2
+       cmp     r12, r1
+       blo     1b
        dsb
- USER( mcr     p15, 0, r0, c7, c5, 1   )       @ invalidate I line
-       add     r0, r0, r2
+       icache_line_size r2, r3
+       sub     r3, r2, #1
+       bic     r12, r0, r3
 2:
-       cmp     r0, r1
-       blo     1b
+ USER( mcr     p15, 0, r12, c7, c5, 1  )       @ invalidate I line
+       add     r12, r12, r2
+       cmp     r12, r1
+       blo     2b
+3:
        mov     r0, #0
        ALT_SMP(mcr     p15, 0, r0, c7, c1, 6)  @ invalidate BTB Inner Shareable
        ALT_UP(mcr      p15, 0, r0, c7, c5, 6)  @ invalidate BTB
@@ -194,10 +201,10 @@ ENTRY(v7_coherent_user_range)
  * isn't mapped, just try the next page.
  */
 9001:
-       mov     r0, r0, lsr #12
-       mov     r0, r0, lsl #12
-       add     r0, r0, #4096
-       b       2b
+       mov     r12, r12, lsr #12
+       mov     r12, r12, lsl #12
+       add     r12, r12, #4096
+       b       3b
  UNWIND(.fnend         )
 ENDPROC(v7_coherent_kern_range)
 ENDPROC(v7_coherent_user_range)
index 7d63beaf97456541c0718c84b475b844194156e6..b795afd0a2c620ad1e8f774b1c166bc8639b2847 100644 (file)
        .endm
 
 /*
- * cache_line_size - get the cache line size from the CSIDR register
- * (available on ARMv7+). It assumes that the CSSR register was configured
- * to access the L1 data cache CSIDR.
+ * dcache_line_size - get the minimum D-cache line size from the CTR register
+ * on ARMv7.
  */
        .macro  dcache_line_size, reg, tmp
-       mrc     p15, 1, \tmp, c0, c0, 0         @ read CSIDR
-       and     \tmp, \tmp, #7                  @ cache line size encoding
-       mov     \reg, #16                       @ size offset
+       mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
+       lsr     \tmp, \tmp, #16
+       and     \tmp, \tmp, #0xf                @ cache line size encoding
+       mov     \reg, #4                        @ bytes per word
        mov     \reg, \reg, lsl \tmp            @ actual cache line size
        .endm
 
+/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register
+ * on ARMv7.
+ */
+       .macro  icache_line_size, reg, tmp
+       mrc     p15, 0, \tmp, c0, c0, 1         @ read ctr
+       and     \tmp, \tmp, #0xf                @ cache line size encoding
+       mov     \reg, #4                        @ bytes per word
+       mov     \reg, \reg, lsl \tmp            @ actual cache line size
+       .endm
 
 /*
  * Sanity check the PTE configuration for the code below - which makes
index 85e6fd212a414efa02526762123b0b4d20653d9a..eda4e3a11a3d1129acbd8885ec67414db2b7638f 100644 (file)
@@ -119,7 +119,7 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
 }
 
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
-                            pin_cfg_t cfg)
+                            pin_cfg_t cfg, bool sleep)
 {
        static const char *afnames[] = {
                [NMK_GPIO_ALT_GPIO]     = "GPIO",
@@ -145,11 +145,34 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
        int output = PIN_DIR(cfg);
        int val = PIN_VAL(cfg);
 
-       dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n",
-               pin, afnames[af], pullnames[pull], slpmnames[slpm],
+       dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
+               pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
                output ? "output " : "input",
                output ? (val ? "high" : "low") : "");
 
+       if (sleep) {
+               int slpm_pull = PIN_SLPM_PULL(cfg);
+               int slpm_output = PIN_SLPM_DIR(cfg);
+               int slpm_val = PIN_SLPM_VAL(cfg);
+
+               /*
+                * The SLPM_* values are normal values + 1 to allow zero to
+                * mean "same as normal".
+                */
+               if (slpm_pull)
+                       pull = slpm_pull - 1;
+               if (slpm_output)
+                       output = slpm_output - 1;
+               if (slpm_val)
+                       val = slpm_val - 1;
+
+               dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
+                       pin,
+                       slpm_pull ? pullnames[pull] : "same",
+                       slpm_output ? (output ? "output" : "input") : "same",
+                       slpm_val ? (val ? "high" : "low") : "same");
+       }
+
        if (output)
                __nmk_gpio_make_output(nmk_chip, offset, val);
        else {
@@ -175,7 +198,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
  * side-effects.  The gpio can be manipulated later using standard GPIO API
  * calls.
  */
-int nmk_config_pin(pin_cfg_t cfg)
+int nmk_config_pin(pin_cfg_t cfg, bool sleep)
 {
        struct nmk_gpio_chip *nmk_chip;
        int gpio = PIN_NUM(cfg);
@@ -186,7 +209,7 @@ int nmk_config_pin(pin_cfg_t cfg)
                return -EINVAL;
 
        spin_lock_irqsave(&nmk_chip->lock, flags);
-       __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg);
+       __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep);
        spin_unlock_irqrestore(&nmk_chip->lock, flags);
 
        return 0;
@@ -207,7 +230,7 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num)
        int i;
 
        for (i = 0; i < num; i++) {
-               int ret = nmk_config_pin(cfgs[i]);
+               ret = nmk_config_pin(cfgs[i], false);
                if (ret)
                        break;
        }
@@ -216,6 +239,21 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num)
 }
 EXPORT_SYMBOL(nmk_config_pins);
 
+int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
+{
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < num; i++) {
+               ret = nmk_config_pin(cfgs[i], true);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(nmk_config_pins_sleep);
+
 /**
  * nmk_gpio_set_slpm() - configure the sleep mode of a pin
  * @gpio: pin number
@@ -634,7 +672,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        chip = &nmk_chip->chip;
        chip->base = pdata->first_gpio;
-       chip->label = pdata->name;
+       chip->label = pdata->name ?: dev_name(&dev->dev);
        chip->dev = &dev->dev;
        chip->owner = THIS_MODULE;
 
index 8c5ae3f2acf8dc6700079008c7058816808f9a62..05a3936ae6d10290772c40a470991810a55a0956 100644 (file)
  *     bit  9..10 - Alternate Function Selection
  *     bit 11..12 - Pull up/down state
  *     bit     13 - Sleep mode behaviour
- *     bit     14 - (sleep mode) Direction
- *     bit     15 - (sleep mode) Value (if output)
+ *     bit     14 - Direction
+ *     bit     15 - Value (if output)
+ *     bit 16..18 - SLPM pull up/down state
+ *     bit 19..20 - SLPM direction
+ *     bit 21..22 - SLPM Value (if output)
  *
  * to facilitate the definition, the following macros are provided
  *
  * PIN_CFG_DEFAULT - default config (0):
  *                  pull up/down = disabled
  *                  sleep mode = input/wakeup
- *                  (sleep mode) direction = input
- *                  (sleep mode) value = low
+ *                  direction = input
+ *                  value = low
+ *                  SLPM direction = same as normal
+ *                  SLPM pull = same as normal
+ *                  SLPM value = same as normal
  *
  * PIN_CFG        - default config with alternate function
  * PIN_CFG_PULL           - default config with alternate function and pull up/down
@@ -75,30 +81,64 @@ typedef unsigned long pin_cfg_t;
 #define PIN_VAL_LOW            (0 << PIN_VAL_SHIFT)
 #define PIN_VAL_HIGH           (1 << PIN_VAL_SHIFT)
 
-/* Shortcuts.  Use these instead of separate DIR and VAL.  */
-#define PIN_INPUT              PIN_DIR_INPUT
+#define PIN_SLPM_PULL_SHIFT    16
+#define PIN_SLPM_PULL_MASK     (0x7 << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL(x)       \
+       (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_NONE     \
+       ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_UP       \
+       ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_DOWN     \
+       ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
+
+#define PIN_SLPM_DIR_SHIFT     19
+#define PIN_SLPM_DIR_MASK      (0x3 << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR(x)                \
+       (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_INPUT     ((1 + 0) << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_OUTPUT    ((1 + 1) << PIN_SLPM_DIR_SHIFT)
+
+#define PIN_SLPM_VAL_SHIFT     21
+#define PIN_SLPM_VAL_MASK      (0x3 << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL(x)                \
+       (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_LOW       ((1 + 0) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_HIGH      ((1 + 1) << PIN_SLPM_VAL_SHIFT)
+
+/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
+#define PIN_INPUT_PULLDOWN     (PIN_DIR_INPUT | PIN_PULL_DOWN)
+#define PIN_INPUT_PULLUP       (PIN_DIR_INPUT | PIN_PULL_UP)
+#define PIN_INPUT_NOPULL       (PIN_DIR_INPUT | PIN_PULL_NONE)
 #define PIN_OUTPUT_LOW         (PIN_DIR_OUTPUT | PIN_VAL_LOW)
 #define PIN_OUTPUT_HIGH                (PIN_DIR_OUTPUT | PIN_VAL_HIGH)
 
-/*
- * These are the same as the ones above, but should make more sense to the
- * reader when seen along with a setting a pin to AF mode.
- */
-#define PIN_SLPM_INPUT         PIN_INPUT
-#define PIN_SLPM_OUTPUT_LOW    PIN_OUTPUT_LOW
-#define PIN_SLPM_OUTPUT_HIGH   PIN_OUTPUT_HIGH
+#define PIN_SLPM_INPUT_PULLDOWN        (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
+#define PIN_SLPM_INPUT_PULLUP  (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
+#define PIN_SLPM_INPUT_NOPULL  (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
+#define PIN_SLPM_OUTPUT_LOW    (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
+#define PIN_SLPM_OUTPUT_HIGH   (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
 
-#define PIN_CFG_DEFAULT                (PIN_PULL_NONE | PIN_SLPM_INPUT)
+#define PIN_CFG_DEFAULT                (0)
 
 #define PIN_CFG(num, alt)              \
        (PIN_CFG_DEFAULT |\
         (PIN_NUM(num) | PIN_##alt))
 
+#define PIN_CFG_INPUT(num, alt, pull)          \
+       (PIN_CFG_DEFAULT |\
+        (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
+
+#define PIN_CFG_OUTPUT(num, alt, val)          \
+       (PIN_CFG_DEFAULT |\
+        (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
+
 #define PIN_CFG_PULL(num, alt, pull)   \
        ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
         (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
 
-extern int nmk_config_pin(pin_cfg_t cfg);
+extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
 extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
+extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
 
 #endif
index 155fe43a672bc47fde734dc76e10fb844e9b22e5..8722a136f3a5bee844f5643dd195c95f077db666 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/err.h>
 
 #include <plat/common.h>
 #include <plat/board.h>
@@ -164,7 +165,7 @@ static int __init omap_init_clocksource_32k(void)
                        return -ENODEV;
 
                sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
-               if (sync_32k_ick)
+               if (!IS_ERR(sync_32k_ick))
                        clk_enable(sync_32k_ick);
 
                clocksource_32k.mult = clocksource_hz2mult(32768,
index e2c8eebe6b3a54a1ab7c0a9ffa25f280117ceb04..74dac419d328297a4347b8a29ce1d5c150af1480 100644 (file)
@@ -166,7 +166,7 @@ static void __init omap_detect_sram(void)
                     cpu_is_omap1710())
                        omap_sram_size = 0x4000;        /* 16K */
                else if (cpu_is_omap1611())
-                       omap_sram_size = 0x3e800;       /* 250K */
+                       omap_sram_size = SZ_256K;
                else {
                        printk(KERN_ERR "Could not detect SRAM size\n");
                        omap_sram_size = 0x4000;
index 4aacdd12c9ccb276d3c4b1809317ee7f104bf0ea..3aca5ba0f87654cf9055a880363f39fedc233473 100644 (file)
@@ -6,6 +6,7 @@ obj-y   := dma.o
 
 obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
 obj-$(CONFIG_PXA3xx)           += mfp.o
+obj-$(CONFIG_PXA95x)           += mfp.o
 obj-$(CONFIG_ARCH_MMP)         += mfp.o
 
 obj-$(CONFIG_HAVE_PWM)         += pwm.o
index 9e604c80618faa092b4083a94663866e60c975a5..75f6564712407feee5e3a20b585047b2519d9fd5 100644 (file)
@@ -423,7 +423,7 @@ typedef unsigned long mfp_cfg_t;
        ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\
         (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm))
 
-#if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP)
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x) || defined(CONFIG_ARCH_MMP)
 /*
  * each MFP pin will have a MFPR register, since the offset of the
  * register varies between processors, the processor specific code
@@ -470,6 +470,6 @@ void mfp_write(int mfp, unsigned long mfpr_val);
 void mfp_config(unsigned long *mfp_cfgs, int num);
 void mfp_config_run(void);
 void mfp_config_lpm(void);
-#endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */
+#endif /* CONFIG_PXA3xx || CONFIG_PXA95x || CONFIG_ARCH_MMP */
 
 #endif /* __ASM_PLAT_MFP_H */
index 76d0858c3cbba1f1cbe4482af23a43a41a8aa019..4a10c0f684b2952cdb0ebf3fe6e33914f0eca9fb 100644 (file)
@@ -88,7 +88,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440000,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2440_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2440_init,
@@ -97,7 +97,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440001,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2440_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2440_init,
@@ -106,7 +106,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440aaa,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2442_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2442_init,
@@ -115,7 +115,7 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440aab,
                .idmask         = 0xffffffff,
-               .map_io         = s3c244x_map_io,
+               .map_io         = s3c2442_map_io,
                .init_clocks    = s3c244x_init_clocks,
                .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2442_init,
index 24c6f5a30596b3d8206ab16d711ab202e5d99ad8..243b6411050d5edfdd587535a65173f9b1343aa7 100644 (file)
@@ -82,8 +82,6 @@ static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
 struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
        .set_config     = s3c_gpio_setcfg_s3c24xx,
        .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_1up,
-       .get_pull       = s3c_gpio_getpull_1up,
 };
 
 struct s3c_gpio_chip s3c24xx_gpios[] = {
index 307248d1ccbbdd052e0b1fc34e69923ed7e104df..89e8d0a25f87454c6672429bd793557acda0fe74 100644 (file)
@@ -21,17 +21,22 @@ extern void s3c244x_init_clocks(int xtal);
 #else
 #define s3c244x_init_clocks NULL
 #define s3c244x_init_uarts NULL
-#define s3c244x_map_io NULL
 #endif
 
 #ifdef CONFIG_CPU_S3C2440
 extern  int s3c2440_init(void);
+
+extern void s3c2440_map_io(void);
 #else
 #define s3c2440_init NULL
+#define s3c2440_map_io NULL
 #endif
 
 #ifdef CONFIG_CPU_S3C2442
 extern  int s3c2442_init(void);
+
+extern void s3c2442_map_io(void);
 #else
 #define s3c2442_init NULL
+#define s3c2442_map_io NULL
 #endif
index b732b773b9aff13fcc4a661b5405618aed363756..0aa32f242ee43097a477a5494f8068723a9386ad 100644 (file)
@@ -280,18 +280,17 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
 }
 #endif
 
-#ifdef CONFIG_S3C_GPIO_PULL_UP
-int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull)
+#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
+static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
+                        unsigned int off, s3c_gpio_pull_t pull,
+                        s3c_gpio_pull_t updown)
 {
        void __iomem *reg = chip->base + 0x08;
        u32 pup = __raw_readl(reg);
 
-       pup = __raw_readl(reg);
-
-       if (pup == S3C_GPIO_PULL_UP)
+       if (pull == updown)
                pup &= ~(1 << off);
-       else if (pup == S3C_GPIO_PULL_NONE)
+       else if (pull == S3C_GPIO_PULL_NONE)
                pup |= (1 << off);
        else
                return -EINVAL;
@@ -300,17 +299,45 @@ int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
        return 0;
 }
 
-s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
+static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
+                                    unsigned int off, s3c_gpio_pull_t updown)
 {
        void __iomem *reg = chip->base + 0x08;
        u32 pup = __raw_readl(reg);
 
        pup &= (1 << off);
-       return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP;
+       return pup ? S3C_GPIO_PULL_NONE : updown;
+}
+#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
+
+#ifdef CONFIG_S3C_GPIO_PULL_UP
+s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
+                                    unsigned int off)
+{
+       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
+}
+
+int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
+                        unsigned int off, s3c_gpio_pull_t pull)
+{
+       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
 }
 #endif /* CONFIG_S3C_GPIO_PULL_UP */
 
+#ifdef CONFIG_S3C_GPIO_PULL_DOWN
+s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
+                                    unsigned int off)
+{
+       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
+}
+
+int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
+                        unsigned int off, s3c_gpio_pull_t pull)
+{
+       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
+}
+#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
+
 #ifdef CONFIG_S5P_GPIO_DRVSTR
 s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
 {
index 8fd65d8b5863121192fa4eff36fcd33f5413a88a..0d2c5703f1eeba843726d1c3511e774d2c94e844 100644 (file)
@@ -209,6 +209,17 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
 extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
                                            unsigned int off);
 
+/**
+ * s3c_gpio_getpull_1down() - Get configuration for choice of down or none
+ * @chip: The gpio chip that the GPIO pin belongs to
+ * @off: The offset to the pin to get the configuration of.
+ *
+ * This helper function reads the state of the pull-down resistor for the
+ * given GPIO in the same case as s3c_gpio_setpull_1down.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
+                                           unsigned int off);
+
 /**
  * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
  * @chip: The gpio chip that is being configured.
index 9768cf7e83d794649438013268ae33151ee9d7a9..9696ddc238c9aa159de79e377e28bcaf326c0b32 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/cnt32_to_63.h>
 #include <linux/io.h>
+#include <linux/sched.h>
 #include <asm/div64.h>
 
 #include <mach/hardware.h>
index 55590a4d87c932984404d1df13ca4c296c9d7117..2fea897ebeb12959415120a7c1cdcaf5d8ac8fee 100644 (file)
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Thu Sep 9 22:43:01 2010
+# Last update: Sun Dec 12 23:24:27 2010
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -2321,7 +2321,7 @@ mx31txtr          MACH_MX31TXTR           MX31TXTR                2332
 u380                   MACH_U380               U380                    2333
 oamp3_hualu            MACH_HUALU_BOARD        HUALU_BOARD             2334
 npcmx50                        MACH_NPCMX50            NPCMX50                 2335
-mx51_lange51           MACH_MX51_LANGE51       MX51_LANGE51            2336
+mx51_efikamx           MACH_MX51_EFIKAMX       MX51_EFIKAMX            2336
 mx51_lange52           MACH_MX51_LANGE52       MX51_LANGE52            2337
 riom                   MACH_RIOM               RIOM                    2338
 comcas                 MACH_COMCAS             COMCAS                  2339
@@ -2355,7 +2355,7 @@ at91sam9263cs             MACH_AT91SAM9263CS      AT91SAM9263CS           2366
 csb732                 MACH_CSB732             CSB732                  2367
 u8500                  MACH_U8500              U8500                   2368
 huqiu                  MACH_HUQIU              HUQIU                   2369
-mx51_kunlun            MACH_MX51_KUNLUN        MX51_KUNLUN             2370
+mx51_efikasb           MACH_MX51_EFIKASB       MX51_EFIKASB            2370
 pmt1g                  MACH_PMT1G              PMT1G                   2371
 htcelf                 MACH_HTCELF             HTCELF                  2372
 armadillo420           MACH_ARMADILLO420       ARMADILLO420            2373
@@ -2971,7 +2971,7 @@ premierwave_en            MACH_PREMIERWAVE_EN     PREMIERWAVE_EN          2985
 wasabi                 MACH_WASABI             WASABI                  2986
 vivow                  MACH_VIVOW              VIVOW                   2987
 mx50_rdp               MACH_MX50_RDP           MX50_RDP                2988
-universal              MACH_UNIVERSAL          UNIVERSAL               2989
+universal_c210         MACH_UNIVERSAL_C210     UNIVERSAL_C210          2989
 real6410               MACH_REAL6410           REAL6410                2990
 spx_sakura             MACH_SPX_SAKURA         SPX_SAKURA              2991
 ij3k_2440              MACH_IJ3K_2440          IJ3K_2440               2992
@@ -3044,3 +3044,178 @@ harvest_desoto          MACH_HARVEST_DESOTO     HARVEST_DESOTO          3059
 msm8x60_qrdc           MACH_MSM8X60_QRDC       MSM8X60_QRDC            3060
 spear900               MACH_SPEAR900           SPEAR900                3061
 pcontrol_g20           MACH_PCONTROL_G20       PCONTROL_G20            3062
+rdstor                 MACH_RDSTOR             RDSTOR                  3063
+usdloader              MACH_USDLOADER          USDLOADER               3064
+tsoploader             MACH_TSOPLOADER         TSOPLOADER              3065
+kronos                 MACH_KRONOS             KRONOS                  3066
+ffcore                 MACH_FFCORE             FFCORE                  3067
+mone                   MACH_MONE               MONE                    3068
+unit2s                 MACH_UNIT2S             UNIT2S                  3069
+acer_a5                        MACH_ACER_A5            ACER_A5                 3070
+etherpro_isp           MACH_ETHERPRO_ISP       ETHERPRO_ISP            3071
+stretchs7000           MACH_STRETCHS7000       STRETCHS7000            3072
+p87_smartsim           MACH_P87_SMARTSIM       P87_SMARTSIM            3073
+tulip                  MACH_TULIP              TULIP                   3074
+sunflower              MACH_SUNFLOWER          SUNFLOWER               3075
+rib                    MACH_RIB                RIB                     3076
+clod                   MACH_CLOD               CLOD                    3077
+rump                   MACH_RUMP               RUMP                    3078
+tenderloin             MACH_TENDERLOIN         TENDERLOIN              3079
+shortloin              MACH_SHORTLOIN          SHORTLOIN               3080
+crespo                 MACH_CRESPO             CRESPO                  3081
+antares                        MACH_ANTARES            ANTARES                 3082
+wb40n                  MACH_WB40N              WB40N                   3083
+herring                        MACH_HERRING            HERRING                 3084
+naxy400                        MACH_NAXY400            NAXY400                 3085
+naxy1200               MACH_NAXY1200           NAXY1200                3086
+vpr200                 MACH_VPR200             VPR200                  3087
+bug20                  MACH_BUG20              BUG20                   3088
+goflexnet              MACH_GOFLEXNET          GOFLEXNET               3089
+torbreck               MACH_TORBRECK           TORBRECK                3090
+saarb_mg1              MACH_SAARB_MG1          SAARB_MG1               3091
+callisto               MACH_CALLISTO           CALLISTO                3092
+multhsu                        MACH_MULTHSU            MULTHSU                 3093
+saluda                 MACH_SALUDA             SALUDA                  3094
+pemp_omap3_apollo      MACH_PEMP_OMAP3_APOLLO  PEMP_OMAP3_APOLLO       3095
+vc0718                 MACH_VC0718             VC0718                  3096
+mvblx                  MACH_MVBLX              MVBLX                   3097
+inhand_apeiron         MACH_INHAND_APEIRON     INHAND_APEIRON          3098
+inhand_fury            MACH_INHAND_FURY        INHAND_FURY             3099
+inhand_siren           MACH_INHAND_SIREN       INHAND_SIREN            3100
+hdnvp                  MACH_HDNVP              HDNVP                   3101
+softwinner             MACH_SOFTWINNER         SOFTWINNER              3102
+prima2_evb             MACH_PRIMA2_EVB         PRIMA2_EVB              3103
+nas6210                        MACH_NAS6210            NAS6210                 3104
+unisdev                        MACH_UNISDEV            UNISDEV                 3105
+sbca11                 MACH_SBCA11             SBCA11                  3106
+saga                   MACH_SAGA               SAGA                    3107
+ns_k330                        MACH_NS_K330            NS_K330                 3108
+tanna                  MACH_TANNA              TANNA                   3109
+imate8502              MACH_IMATE8502          IMATE8502               3110
+aspen                  MACH_ASPEN              ASPEN                   3111
+daintree_cwac          MACH_DAINTREE_CWAC      DAINTREE_CWAC           3112
+zmx25                  MACH_ZMX25              ZMX25                   3113
+maple1                 MACH_MAPLE1             MAPLE1                  3114
+qsd8x72_surf           MACH_QSD8X72_SURF       QSD8X72_SURF            3115
+qsd8x72_ffa            MACH_QSD8X72_FFA        QSD8X72_FFA             3116
+abilene                        MACH_ABILENE            ABILENE                 3117
+eigen_ttr              MACH_EIGEN_TTR          EIGEN_TTR               3118
+iomega_ix2_200         MACH_IOMEGA_IX2_200     IOMEGA_IX2_200          3119
+coretec_vcx7400                MACH_CORETEC_VCX7400    CORETEC_VCX7400         3120
+santiago               MACH_SANTIAGO           SANTIAGO                3121
+mx257sol               MACH_MX257SOL           MX257SOL                3122
+strasbourg             MACH_STRASBOURG         STRASBOURG              3123
+msm8x60_fluid          MACH_MSM8X60_FLUID      MSM8X60_FLUID           3124
+smartqv5               MACH_SMARTQV5           SMARTQV5                3125
+smartqv3               MACH_SMARTQV3           SMARTQV3                3126
+smartqv7               MACH_SMARTQV7           SMARTQV7                3127
+paz00                  MACH_PAZ00              PAZ00                   3128
+acmenetusfoxg20                MACH_ACMENETUSFOXG20    ACMENETUSFOXG20         3129
+htcwillow              MACH_HTCWILLOW          HTCWILLOW               3130
+fwbd_0404              MACH_FWBD_0404          FWBD_0404               3131
+hdgu                   MACH_HDGU               HDGU                    3132
+pyramid                        MACH_PYRAMID            PYRAMID                 3133
+epiphan                        MACH_EPIPHAN            EPIPHAN                 3134
+omap_bender            MACH_OMAP_BENDER        OMAP_BENDER             3135
+gurnard                        MACH_GURNARD            GURNARD                 3136
+gtl_it5100             MACH_GTL_IT5100         GTL_IT5100              3137
+bcm2708                        MACH_BCM2708            BCM2708                 3138
+mx51_ggc               MACH_MX51_GGC           MX51_GGC                3139
+sharespace             MACH_SHARESPACE         SHARESPACE              3140
+haba_knx_explorer      MACH_HABA_KNX_EXPLORER  HABA_KNX_EXPLORER       3141
+simtec_kirkmod         MACH_SIMTEC_KIRKMOD     SIMTEC_KIRKMOD          3142
+crux                   MACH_CRUX               CRUX                    3143
+mx51_bravo             MACH_MX51_BRAVO         MX51_BRAVO              3144
+charon                 MACH_CHARON             CHARON                  3145
+picocom3               MACH_PICOCOM3           PICOCOM3                3146
+picocom4               MACH_PICOCOM4           PICOCOM4                3147
+serrano                        MACH_SERRANO            SERRANO                 3148
+doubleshot             MACH_DOUBLESHOT         DOUBLESHOT              3149
+evsy                   MACH_EVSY               EVSY                    3150
+huashan                        MACH_HUASHAN            HUASHAN                 3151
+lausanne               MACH_LAUSANNE           LAUSANNE                3152
+emerald                        MACH_EMERALD            EMERALD                 3153
+tqma35                 MACH_TQMA35             TQMA35                  3154
+marvel                 MACH_MARVEL             MARVEL                  3155
+manuae                 MACH_MANUAE             MANUAE                  3156
+chacha                 MACH_CHACHA             CHACHA                  3157
+lemon                  MACH_LEMON              LEMON                   3158
+csc                    MACH_CSC                CSC                     3159
+gira_knxip_router      MACH_GIRA_KNXIP_ROUTER  GIRA_KNXIP_ROUTER       3160
+t20                    MACH_T20                T20                     3161
+hdmini                 MACH_HDMINI             HDMINI                  3162
+sciphone_g2            MACH_SCIPHONE_G2        SCIPHONE_G2             3163
+express                        MACH_EXPRESS            EXPRESS                 3164
+express_kt             MACH_EXPRESS_KT         EXPRESS_KT              3165
+maximasp               MACH_MAXIMASP           MAXIMASP                3166
+nitrogen_imx51         MACH_NITROGEN_IMX51     NITROGEN_IMX51          3167
+nitrogen_imx53         MACH_NITROGEN_IMX53     NITROGEN_IMX53          3168
+sunfire                        MACH_SUNFIRE            SUNFIRE                 3169
+arowana                        MACH_AROWANA            AROWANA                 3170
+tegra_daytona          MACH_TEGRA_DAYTONA      TEGRA_DAYTONA           3171
+tegra_swordfish                MACH_TEGRA_SWORDFISH    TEGRA_SWORDFISH         3172
+edison                 MACH_EDISON             EDISON                  3173
+svp8500v1              MACH_SVP8500V1          SVP8500V1               3174
+svp8500v2              MACH_SVP8500V2          SVP8500V2               3175
+svp5500                        MACH_SVP5500            SVP5500                 3176
+b5500                  MACH_B5500              B5500                   3177
+s5500                  MACH_S5500              S5500                   3178
+icon                   MACH_ICON               ICON                    3179
+elephant               MACH_ELEPHANT           ELEPHANT                3180
+msm8x60_fusion         MACH_MSM8X60_FUSION     MSM8X60_FUSION          3181
+shooter                        MACH_SHOOTER            SHOOTER                 3182
+spade_lte              MACH_SPADE_LTE          SPADE_LTE               3183
+philhwani              MACH_PHILHWANI          PHILHWANI               3184
+gsncomm                        MACH_GSNCOMM            GSNCOMM                 3185
+strasbourg_a2          MACH_STRASBOURG_A2      STRASBOURG_A2           3186
+mmm                    MACH_MMM                MMM                     3187
+davinci_dm365_bv       MACH_DAVINCI_DM365_BV   DAVINCI_DM365_BV        3188
+ag5evm                 MACH_AG5EVM             AG5EVM                  3189
+sc575plc               MACH_SC575PLC           SC575PLC                3190
+sc575hmi               MACH_SC575IPC           SC575IPC                3191
+omap3_tdm3730          MACH_OMAP3_TDM3730      OMAP3_TDM3730           3192
+g7                     MACH_G7                 G7                      3193
+top9000_eval           MACH_TOP9000_EVAL       TOP9000_EVAL            3194
+top9000_su             MACH_TOP9000_SU         TOP9000_SU              3195
+utm300                 MACH_UTM300             UTM300                  3196
+tsunagi                        MACH_TSUNAGI            TSUNAGI                 3197
+ts75xx                 MACH_TS75XX             TS75XX                  3198
+msm8x60_fusn_ffa       MACH_MSM8X60_FUSN_FFA   MSM8X60_FUSN_FFA        3199
+ts47xx                 MACH_TS47XX             TS47XX                  3200
+da850_k5               MACH_DA850_K5           DA850_K5                3201
+ax502                  MACH_AX502              AX502                   3202
+igep0032               MACH_IGEP0032           IGEP0032                3203
+antero                 MACH_ANTERO             ANTERO                  3204
+synergy                        MACH_SYNERGY            SYNERGY                 3205
+ics_if_voip            MACH_ICS_IF_VOIP        ICS_IF_VOIP             3206
+wlf_cragg_6410         MACH_WLF_CRAGG_6410     WLF_CRAGG_6410          3207
+punica                 MACH_PUNICA             PUNICA                  3208
+sbc_nt250              MACH_SBC_NT250          SBC_NT250               3209
+mx27_wmultra           MACH_MX27_WMULTRA       MX27_WMULTRA            3210
+mackerel               MACH_MACKEREL           MACKEREL                3211
+fa9x27                 MACH_FA9X27             FA9X27                  3213
+ns2816tb               MACH_NS2816TB           NS2816TB                3214
+ns2816_ntpad           MACH_NS2816_NTPAD       NS2816_NTPAD            3215
+ns2816_ntnb            MACH_NS2816_NTNB        NS2816_NTNB             3216
+kaen                   MACH_KAEN               KAEN                    3217
+nv1000                 MACH_NV1000             NV1000                  3218
+nuc950ts               MACH_NUC950TS           NUC950TS                3219
+nokia_rm680            MACH_NOKIA_RM680        NOKIA_RM680             3220
+ast2200                        MACH_AST2200            AST2200                 3221
+lead                   MACH_LEAD               LEAD                    3222
+unino1                 MACH_UNINO1             UNINO1                  3223
+greeco                 MACH_GREECO             GREECO                  3224
+verdi                  MACH_VERDI              VERDI                   3225
+dm6446_adbox           MACH_DM6446_ADBOX       DM6446_ADBOX            3226
+quad_salsa             MACH_QUAD_SALSA         QUAD_SALSA              3227
+abb_gma_1_1            MACH_ABB_GMA_1_1        ABB_GMA_1_1             3228
+svcid                  MACH_SVCID              SVCID                   3229
+msm8960_sim            MACH_MSM8960_SIM        MSM8960_SIM             3230
+msm8960_rumi3          MACH_MSM8960_RUMI3      MSM8960_RUMI3           3231
+icon_g                 MACH_ICON_G             ICON_G                  3232
+mb3                    MACH_MB3                MB3                     3233
+gsia18s                        MACH_GSIA18S            GSIA18S                 3234
+pivicc                 MACH_PIVICC             PIVICC                  3235
+pcm048                 MACH_PCM048             PCM048                  3236
+dds                    MACH_DDS                DDS                     3237
+chalten_xa1            MACH_CHALTEN_XA1        CHALTEN_XA1             3238
index 0d5d63c91dc3ee74457d183a11d59a149022d0c5..f28dc99c6f729a23ba20cd73dd1bb39d80917cda 100644 (file)
@@ -73,7 +73,8 @@ void gdbstub_io_init(void)
        GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
 
        /* permit level 0 IRQs to take place */
-       local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+       arch_local_change_intr_mask_level(
+               NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
 }
 
 /*
index 97dfda23342c8d9fe8aef19d8c9d4dfaeb170a7d..abdeea153c89643184df8f7b1c13805a504b0b7a 100644 (file)
@@ -87,7 +87,8 @@ void __init gdbstub_io_init(void)
        tmp = *gdbstub_port->_control;
 
        /* permit level 0 IRQs only */
-       local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+       arch_local_change_intr_mask_level(
+               NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
 }
 
 /*
index a5fc3f05309b2fc26960a36fe68ef1339683c4fd..b169d99d9f20e8fd4b5da5ea353b70f02819844b 100644 (file)
@@ -1194,7 +1194,8 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
 
        asm volatile("mov mdr,%0" : "=d"(mdr));
        local_save_flags(epsw);
-       local_change_intr_mask_level(NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+       arch_local_change_intr_mask_level(
+               NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
 
        gdbstub_store_fpu();
 
index 7f217b3a50a806b7347f991b588397011aa3388e..2e9d78d21fd36f9648286b2eb46df84beb4c9816 100644 (file)
@@ -22,7 +22,8 @@ config SUPERH
        select HAVE_SPARSE_IRQ
        select RTC_LIB
        select GENERIC_ATOMIC64
-       select GENERIC_HARDIRQS_NO_DEPRECATED
+       # Support the deprecated APIs until MFD and GPIOLIB catch up.
+       select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
index 903cd618eb740606853662d23765a694044e586c..d6741fca89a4f2d42b763d9789c5b81dc574988e 100644 (file)
 #define __NR_sendmsg           355
 #define __NR_recvmsg           356
 #define __NR_recvmmsg          357
+#define __NR_accept4           358
 
-#define NR_syscalls 358
+#define NR_syscalls 359
 
 #ifdef __KERNEL__
 
index e872e81add8a96ed12709964768a699f8a50306d..6fc347ebe59dfe0a356fe4d2d4f31ea52fa69206 100644 (file)
@@ -375,3 +375,4 @@ ENTRY(sys_call_table)
        .long sys_sendmsg               /* 355 */
        .long sys_recvmsg
        .long sys_recvmmsg
+       .long sys_accept4
index 81cd43432dc0ea5027eb0757ae2e27e2b13c5358..47eaafad15ceb63c8de66a8ef573d8fed32a714d 100644 (file)
@@ -39,7 +39,7 @@ struct linux_dev_v2_funcs {
        int (*v2_dev_open)(char *devpath);
        void (*v2_dev_close)(int d);
        int (*v2_dev_read)(int d, char *buf, int nbytes);
-       int (*v2_dev_write)(int d, char *buf, int nbytes);
+       int (*v2_dev_write)(int d, const char *buf, int nbytes);
        int (*v2_dev_seek)(int d, int hi, int lo);
 
        /* Never issued (multistage load support) */
index 51296a6f5005389877ca17c234f670fa71a3f8c0..9e5c64084b865781ca6782ced49b670ae35a5490 100644 (file)
@@ -60,25 +60,6 @@ extern char *prom_getbootargs(void);
 extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes);
 extern void prom_unmapio(char *virt_addr, unsigned int num_bytes);
 
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-                     unsigned int seek_lowval);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
@@ -121,19 +102,8 @@ extern int prom_getrev(void);
 /* Get the prom firmware revision. */
 extern int prom_getprev(void);
 
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
+/* Write a buffer of characters to the console. */
+extern void prom_console_write_buf(const char *buf, int len);
 
 /* Prom's internal routines, don't use in kernel/boot code. */
 extern void prom_printf(const char *fmt, ...);
@@ -238,7 +208,6 @@ extern int prom_node_has_property(phandle node, char *property);
 extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern phandle prom_pathtoinode(char *path);
 extern phandle prom_inst2pkg(int);
 
 /* Dorking with Bus ranges... */
index c9cc078e3e31531522fe5d531abcb0b72a1980b2..8cd0df34e82b86ada58f1399a8dab12a260adacb 100644 (file)
@@ -67,27 +67,6 @@ extern void prom_init(void *cif_handler, void *cif_stack);
 /* Boot argument acquisition, returns the boot command line string. */
 extern char *prom_getbootargs(void);
 
-/* Device utilities. */
-
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(const char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-                     unsigned int seek_lowval);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
@@ -109,33 +88,14 @@ extern void prom_halt(void) __attribute__ ((noreturn));
 /* Halt and power-off the machine. */
 extern void prom_halt_power_off(void) __attribute__ ((noreturn));
 
-/* Set the PROM 'sync' callback function to the passed function pointer.
- * When the user gives the 'sync' command at the prom prompt while the
- * kernel is still active, the prom will call this routine.
- *
- */
-typedef int (*callback_func_t)(long *cmd);
-extern void prom_setcallback(callback_func_t func_ptr);
-
 /* Acquire the IDPROM of the root node in the prom device tree.  This
  * gets passed a buffer where you would like it stuffed.  The return value
  * is the format type of this idprom or 0xff on error.
  */
 extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
 
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
+/* Write a buffer of characters to the console. */
+extern void prom_console_write_buf(const char *buf, int len);
 
 /* Prom's internal routines, don't use in kernel/boot code. */
 extern void prom_printf(const char *fmt, ...);
@@ -279,9 +239,7 @@ extern phandle prom_finddevice(const char *name);
 extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern phandle prom_pathtoinode(const char *path);
 extern phandle prom_inst2pkg(int);
-extern int prom_service_exists(const char *service_name);
 extern void prom_sun4v_guest_soft_state(void);
 
 extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
index 2d51527d810fc811531dae33c4bafc281b47d924..f01c42661ee51283183e6b6588297d20a78ec392 100644 (file)
@@ -114,7 +114,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
        if (leon3_gptimer_regs && leon3_irqctrl_regs) {
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
-                                     (((1000000 / 100) - 1)));
+                                     (((1000000 / HZ) - 1)));
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
 
 #ifdef CONFIG_SMP
@@ -128,7 +128,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
                }
 
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0);
-               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/100) - 1)));
+               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1)));
                LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
 # endif
 
index 1b8c073adb44fe341b883f87865b28531d61b95f..816c0fa12dc0f546b94b58a728a24197adb48d22 100644 (file)
@@ -6,7 +6,6 @@ ccflags := -Werror
 
 lib-y                 := bootstr_$(BITS).o
 lib-$(CONFIG_SPARC32) += devmap.o
-lib-y                 += devops_$(BITS).o
 lib-y                 += init_$(BITS).o
 lib-$(CONFIG_SPARC32) += memory.o
 lib-y                 += misc_$(BITS).o
index 5340264b78f57c79dcd4f031d8348d31e9df1100..48863108a44ce6af379436c7f32ba2063e39a3f2 100644 (file)
 
 extern void restore_current(void);
 
-/* Non blocking get character from console input device, returns -1
- * if no input was taken.  This can be used for polling.
- */
-int
-prom_nbgetchar(void)
-{
-       static char inc;
-       int i = -1;
-       unsigned long flags;
-
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               i = (*(romvec->pv_nbgetchar))();
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) {
-                       i = inc;
-               } else {
-                       i = -1;
-               }
-               break;
-       default:
-               i = -1;
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-       return i; /* Ugh, we could spin forever on unsupported proms ;( */
-}
-
 /* Non blocking put character to console device, returns -1 if
  * unsuccessful.
  */
-int
-prom_nbputchar(char c)
+static int prom_nbputchar(const char *buf)
 {
-       static char outc;
        unsigned long flags;
        int i = -1;
 
        spin_lock_irqsave(&prom_lock, flags);
        switch(prom_vers) {
        case PROM_V0:
-               i = (*(romvec->pv_nbputchar))(c);
+               i = (*(romvec->pv_nbputchar))(*buf);
                break;
        case PROM_V2:
        case PROM_V3:
-               outc = c;
-               if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1)
+               if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout,
+                                                         buf, 0x1) == 1)
                        i = 0;
-               else
-                       i = -1;
                break;
        default:
-               i = -1;
                break;
        };
        restore_current();
@@ -80,18 +43,14 @@ prom_nbputchar(char c)
        return i; /* Ugh, we could spin forever on unsupported proms ;( */
 }
 
-/* Blocking version of get character routine above. */
-char
-prom_getchar(void)
+void prom_console_write_buf(const char *buf, int len)
 {
-       int character;
-       while((character = prom_nbgetchar()) == -1) ;
-       return (char) character;
+       while (len) {
+               int n = prom_nbputchar(buf);
+               if (n)
+                       continue;
+               len--;
+               buf++;
+       }
 }
 
-/* Blocking version of put character routine above. */
-void
-prom_putchar(char c)
-{
-       while(prom_nbputchar(c) == -1) ;
-}
index 10322dc2f557a22d5befcc17dd4a27d8b6604f89..ed39e75828bd1eb6057f192d052ab88f5b943ddd 100644 (file)
 
 extern int prom_stdin, prom_stdout;
 
-/* Non blocking get character from console input device, returns -1
- * if no input was taken.  This can be used for polling.
- */
-inline int
-prom_nbgetchar(void)
-{
-       unsigned long args[7];
-       char inc;
-
-       args[0] = (unsigned long) "read";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) prom_stdin;
-       args[4] = (unsigned long) &inc;
-       args[5] = 1;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-
-       if (args[6] == 1)
-               return inc;
-       return -1;
-}
-
-/* Non blocking put character to console device, returns -1 if
- * unsuccessful.
- */
-inline int
-prom_nbputchar(char c)
+static int __prom_console_write_buf(const char *buf, int len)
 {
        unsigned long args[7];
-       char outc;
-       
-       outc = c;
+       int ret;
 
        args[0] = (unsigned long) "write";
        args[1] = 3;
        args[2] = 1;
        args[3] = (unsigned int) prom_stdout;
-       args[4] = (unsigned long) &outc;
-       args[5] = 1;
+       args[4] = (unsigned long) buf;
+       args[5] = (unsigned int) len;
        args[6] = (unsigned long) -1;
 
        p1275_cmd_direct(args);
 
-       if (args[6] == 1)
-               return 0;
-       else
+       ret = (int) args[6];
+       if (ret < 0)
                return -1;
+       return ret;
 }
 
-/* Blocking version of get character routine above. */
-char
-prom_getchar(void)
-{
-       int character;
-       while((character = prom_nbgetchar()) == -1) ;
-       return (char) character;
-}
-
-/* Blocking version of put character routine above. */
-void
-prom_putchar(char c)
+void prom_console_write_buf(const char *buf, int len)
 {
-       prom_nbputchar(c);
-}
-
-void
-prom_puts(const char *s, int len)
-{
-       unsigned long args[7];
-
-       args[0] = (unsigned long) "write";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) prom_stdout;
-       args[4] = (unsigned long) s;
-       args[5] = len;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
+       while (len) {
+               int n = __prom_console_write_buf(buf, len);
+               if (n < 0)
+                       continue;
+               len -= n;
+               buf += len;
+       }
 }
diff --git a/arch/sparc/prom/devops_32.c b/arch/sparc/prom/devops_32.c
deleted file mode 100644 (file)
index 9c5d468..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * devops.c:  Device operations using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-extern void restore_current(void);
-
-/* Open the device described by the string 'dstr'.  Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns -1 on failure.
- */
-int
-prom_devopen(char *dstr)
-{
-       int handle;
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               handle = (*(romvec->pv_v0devops.v0_devopen))(dstr);
-               if(handle == 0) handle = -1;
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               handle = (*(romvec->pv_v2devops.v2_dev_open))(dstr);
-               break;
-       default:
-               handle = -1;
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-
-       return handle;
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               (*(romvec->pv_v0devops.v0_devclose))(dhandle);
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               (*(romvec->pv_v2devops.v2_dev_close))(dhandle);
-               break;
-       default:
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-       return 0;
-}
-
-/* Seek to specified location described by 'seekhi' and 'seeklo'
- * for device 'dhandle'.
- */
-void
-prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&prom_lock, flags);
-       switch(prom_vers) {
-       case PROM_V0:
-               (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo);
-               break;
-       case PROM_V2:
-       case PROM_V3:
-               (*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo);
-               break;
-       default:
-               break;
-       };
-       restore_current();
-       spin_unlock_irqrestore(&prom_lock, flags);
-}
diff --git a/arch/sparc/prom/devops_64.c b/arch/sparc/prom/devops_64.c
deleted file mode 100644 (file)
index a017119..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * devops.c:  Device operations using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-/* Open the device described by the string 'dstr'.  Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns 0 on failure.
- */
-int
-prom_devopen(const char *dstr)
-{
-       unsigned long args[5];
-
-       args[0] = (unsigned long) "open";
-       args[1] = 1;
-       args[2] = 1;
-       args[3] = (unsigned long) dstr;
-       args[4] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-
-       return (int) args[4];
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
-       unsigned long args[4];
-
-       args[0] = (unsigned long) "close";
-       args[1] = 1;
-       args[2] = 0;
-       args[3] = (unsigned int) dhandle;
-
-       p1275_cmd_direct(args);
-
-       return 0;
-}
-
-/* Seek to specified location described by 'seekhi' and 'seeklo'
- * for device 'dhandle'.
- */
-void
-prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
-{
-       unsigned long args[7];
-
-       args[0] = (unsigned long) "seek";
-       args[1] = 3;
-       args[2] = 1;
-       args[3] = (unsigned int) dhandle;
-       args[4] = seekhi;
-       args[5] = seeklo;
-       args[6] = (unsigned long) -1;
-
-       p1275_cmd_direct(args);
-}
index d24bc44e361ee20b654960cc7784176670705da6..e4f31d4d3715cc5c27752633ba58e052e853a956 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/system.h>
 #include <asm/ldc.h>
 
-int prom_service_exists(const char *service_name)
+static int prom_service_exists(const char *service_name)
 {
        unsigned long args[5];
 
@@ -150,20 +150,6 @@ void prom_halt_power_off(void)
        prom_halt();
 }
 
-/* Set prom sync handler to call function 'funcp'. */
-void prom_setcallback(callback_func_t funcp)
-{
-       unsigned long args[5];
-       if (!funcp)
-               return;
-       args[0] = (unsigned long) "set-callback";
-       args[1] = 1;
-       args[2] = 1;
-       args[3] = (unsigned long) funcp;
-       args[4] = (unsigned long) -1;
-       p1275_cmd_direct(args);
-}
-
 /* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
  * format type.  'num_bytes' is the number of bytes that your idbuf
  * has space for.  Returns 0xff on error.
index ca869266b9f3d0106e60d7b8c28f5cdcf614826b..d9682f06b3b056c7862ec7cda4214a95ab213a03 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/compiler.h>
+#include <linux/spinlock.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
+#define CONSOLE_WRITE_BUF_SIZE 1024
+
 static char ppbuf[1024];
+static char console_write_buf[CONSOLE_WRITE_BUF_SIZE];
+static DEFINE_RAW_SPINLOCK(console_write_lock);
 
 void notrace prom_write(const char *buf, unsigned int n)
 {
-       char ch;
+       unsigned int dest_len;
+       unsigned long flags;
+       char *dest;
+
+       dest = console_write_buf;
+       raw_spin_lock_irqsave(&console_write_lock, flags);
 
-       while (n != 0) {
-               --n;
-               if ((ch = *buf++) == '\n')
-                       prom_putchar('\r');
-               prom_putchar(ch);
+       dest_len = 0;
+       while (n-- != 0) {
+               char ch = *buf++;
+               if (ch == '\n') {
+                       *dest++ = '\r';
+                       dest_len++;
+               }
+               *dest++ = ch;
+               dest_len++;
+               if (dest_len >= CONSOLE_WRITE_BUF_SIZE - 1) {
+                       prom_console_write_buf(console_write_buf, dest_len);
+                       dest = console_write_buf;
+                       dest_len = 0;
+               }
        }
+       if (dest_len)
+               prom_console_write_buf(console_write_buf, dest_len);
+
+       raw_spin_unlock_irqrestore(&console_write_lock, flags);
 }
 
 void notrace prom_printf(const char *fmt, ...)
index 63e08e149774fc6a0a30fcd9228abb83f434aae7..535e2e69ac1d8287470356218511c25af6be7a8c 100644 (file)
@@ -342,19 +342,3 @@ phandle prom_inst2pkg(int inst)
        if (node == -1) return 0;
        return node;
 }
-
-/* Return 'node' assigned to a particular prom 'path'
- * FIXME: Should work for v0 as well
- */
-phandle prom_pathtoinode(char *path)
-{
-       phandle node;
-       int inst;
-       
-       inst = prom_devopen (path);
-       if (inst == -1) return 0;
-       node = prom_inst2pkg (inst);
-       prom_devclose (inst);
-       if (node == -1) return 0;
-       return node;
-}
index 691be68932f84cf7d804b2a7ce6720fceeedc447..d93660048376c9d9bf4478720a6825e9e7b117ed 100644 (file)
@@ -374,24 +374,6 @@ inline phandle prom_inst2pkg(int inst)
        return node;
 }
 
-/* Return 'node' assigned to a particular prom 'path'
- * FIXME: Should work for v0 as well
- */
-phandle prom_pathtoinode(const char *path)
-{
-       phandle node;
-       int inst;
-
-       inst = prom_devopen (path);
-       if (inst == 0)
-               return 0;
-       node = prom_inst2pkg(inst);
-       prom_devclose(inst);
-       if (node == -1)
-               return 0;
-       return node;
-}
-
 int prom_ihandle2path(int handle, char *buffer, int bufsize)
 {
        unsigned long args[7];
index cbcc8d8ea93a9144471fede4aeca15bdb4780203..7a6e68e4f748fc2db4af59f42d4c1caad9460060 100644 (file)
@@ -10,6 +10,7 @@
  * by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
index 7f7e577a0e39cfca111c5a0b4718480b01c86170..31d84acc15125646018914b51a758821ec796590 100644 (file)
@@ -11,6 +11,7 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
 void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
                            struct pvclock_vcpu_time_info *vcpu,
                            struct timespec *ts);
+void pvclock_resume(void);
 
 /*
  * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
index 008b91eefa188139f57f7b77de6c7aef6240ef08..42eb3300dfc6c35630aab267e051678f1a677e59 100644 (file)
@@ -83,6 +83,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
 
 static atomic64_t last_value = ATOMIC64_INIT(0);
 
+void pvclock_resume(void)
+{
+       atomic64_set(&last_value, 0);
+}
+
 cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
 {
        struct pvclock_shadow_time shadow;
index b2bb5aa3b0540e42847a7664aa529cf5d2c0fb83..5da5e53fb94c20bf6c244dce734e515c92d10b34 100644 (file)
@@ -426,6 +426,8 @@ void xen_timer_resume(void)
 {
        int cpu;
 
+       pvclock_resume();
+
        if (xen_clockevent != &xen_vcpuop_clockevent)
                return;
 
index f20d6a789d484591e9fdb5642fa893c233c2b9b0..0c8b64a16484721308587c7a6b635344a9144a1e 100644 (file)
@@ -250,6 +250,14 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
        int ret, rw;
        unsigned int dxfer_len;
        void *dxferp = NULL;
+       struct bsg_class_device *bcd = &q->bsg_dev;
+
+       /* if the LLD has been removed then the bsg_unregister_queue will
+        * eventually be called and the class_dev was freed, so we can no
+        * longer use this request_queue. Return no such address.
+        */
+       if (!bcd->class_dev)
+               return ERR_PTR(-ENXIO);
 
        dprintk("map hdr %llx/%u %llx/%u\n", (unsigned long long) hdr->dout_xferp,
                hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
index ba9afeaa23acfb676021c86432fd89b45f8ba5cf..25d3aaebc10d4d86238c0af67bcb01976b6dcd65 100644 (file)
@@ -100,24 +100,7 @@ static const struct file_operations acpi_ac_fops = {
        .release = single_release,
 };
 #endif
-static int get_ac_property(struct power_supply *psy,
-                          enum power_supply_property psp,
-                          union power_supply_propval *val)
-{
-       struct acpi_ac *ac = to_acpi_ac(psy);
-       switch (psp) {
-       case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = ac->state;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
 
-static enum power_supply_property ac_props[] = {
-       POWER_SUPPLY_PROP_ONLINE,
-};
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
@@ -140,6 +123,35 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
        return 0;
 }
 
+/* --------------------------------------------------------------------------
+                            sysfs I/F
+   -------------------------------------------------------------------------- */
+static int get_ac_property(struct power_supply *psy,
+                          enum power_supply_property psp,
+                          union power_supply_propval *val)
+{
+       struct acpi_ac *ac = to_acpi_ac(psy);
+
+       if (!ac)
+               return -ENODEV;
+
+       if (acpi_ac_get_state(ac))
+               return -ENODEV;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = ac->state;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static enum power_supply_property ac_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
 #ifdef CONFIG_ACPI_PROCFS_POWER
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
index 1211c03149e8c7c258fee89dd1109e1e6b901c26..5850d320404c35b9c7318eb0619ae54c7e32a30b 100644 (file)
@@ -86,7 +86,7 @@ static struct erst_erange {
  * It is used to provide exclusive accessing for ERST Error Log
  * Address Range too.
  */
-static DEFINE_SPINLOCK(erst_lock);
+static DEFINE_RAW_SPINLOCK(erst_lock);
 
 static inline int erst_errno(int command_status)
 {
@@ -421,9 +421,9 @@ ssize_t erst_get_record_count(void)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        count = __erst_get_record_count();
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return count;
 }
@@ -456,9 +456,9 @@ int erst_get_next_record_id(u64 *record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -624,17 +624,17 @@ int erst_write(const struct cper_record_header *record)
                return -EINVAL;
 
        if (erst_erange.attr & ERST_RANGE_NVRAM) {
-               if (!spin_trylock_irqsave(&erst_lock, flags))
+               if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                        return -EBUSY;
                rc = __erst_write_to_nvram(record);
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
 
        if (record->record_length > erst_erange.size)
                return -EINVAL;
 
-       if (!spin_trylock_irqsave(&erst_lock, flags))
+       if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                return -EBUSY;
        memcpy(erst_erange.vaddr, record, record->record_length);
        rcd_erange = erst_erange.vaddr;
@@ -642,7 +642,7 @@ int erst_write(const struct cper_record_header *record)
        memcpy(&rcd_erange->persistence_information, "ER", 2);
 
        rc = __erst_write_to_storage(0);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -696,9 +696,9 @@ ssize_t erst_read(u64 record_id, struct cper_record_header *record,
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
        return len;
 }
 EXPORT_SYMBOL_GPL(erst_read);
@@ -719,20 +719,20 @@ ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(&record_id);
        if (rc) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
        /* no more record */
        if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return 0;
        }
 
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return len;
 }
@@ -746,12 +746,12 @@ int erst_clear(u64 record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        if (erst_erange.attr & ERST_RANGE_NVRAM)
                rc = __erst_clear_from_nvram(record_id);
        else
                rc = __erst_clear_from_storage(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
index 1a3508a7fe03f157c2e0144727bbeb5c244d2a46..daa7bc63f1d4bad00fd988ddcce3681fdc74f804 100644 (file)
@@ -46,9 +46,9 @@ EXPORT_SYMBOL_GPL(hest_disable);
 
 /* HEST table parsing */
 
-static struct acpi_table_hest *hest_tab;
+static struct acpi_table_hest *__read_mostly hest_tab;
 
-static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
+static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
        [ACPI_HEST_TYPE_IA32_CHECK] = -1,       /* need further calculation */
        [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1,
        [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi),
@@ -126,7 +126,7 @@ struct ghes_arr {
        unsigned int count;
 };
 
-static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
 {
        int *count = data;
 
@@ -135,7 +135,7 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
        return 0;
 }
 
-static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
 {
        struct platform_device *ghes_dev;
        struct ghes_arr *ghes_arr = data;
@@ -165,7 +165,7 @@ err:
        return rc;
 }
 
-static int hest_ghes_dev_register(unsigned int ghes_count)
+static int __init hest_ghes_dev_register(unsigned int ghes_count)
 {
        int rc, i;
        struct ghes_arr ghes_arr;
index 95649d373071ac93d14bbbb478db1ab4a8cdb801..9fb9d5ac939db1c071c4cdcaa7fba49364236e25 100644 (file)
@@ -130,6 +130,8 @@ struct acpi_battery {
        unsigned long flags;
 };
 
+static int acpi_battery_update(struct acpi_battery *battery);
+
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -184,6 +186,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
        int ret = 0;
        struct acpi_battery *battery = to_acpi_battery(psy);
 
+       if (acpi_battery_update(battery))
+               return -ENODEV;
+
        if (acpi_battery_present(battery)) {
                /* run battery update only if it is present */
                acpi_battery_get_state(battery);
index 372ff80b7b0c93f88f6f2ea9e100c0fdd2aaf6bf..302b31ed31f1ea099faa48b989114e9c99dc1485 100644 (file)
@@ -934,6 +934,9 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
        ec_flag_msi, "MSI hardware", {
        DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
        {
+       ec_flag_msi, "MSI hardware", {
+       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL},
+       {
        ec_validate_ecdt, "ASUS hardware", {
        DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
        {},
index 966feddf6b1ba29457fde294223018ad23666e39..055d7b701fff16d18fe5de5ea243ba8ec477e3ec 100644 (file)
@@ -110,9 +110,6 @@ struct acpi_ioremap {
 static LIST_HEAD(acpi_ioremaps);
 static DEFINE_SPINLOCK(acpi_ioremap_lock);
 
-#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
-static char osi_setup_string[OSI_STRING_LENGTH_MAX];
-
 static void __init acpi_osi_setup_late(void);
 
 /*
@@ -152,8 +149,7 @@ static struct osi_linux {
        unsigned int    enable:1;
        unsigned int    dmi:1;
        unsigned int    cmdline:1;
-       unsigned int    known:1;
-} osi_linux = { 0, 0, 0, 0};
+} osi_linux = {0, 0, 0};
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
 {
@@ -1055,13 +1051,53 @@ static int __init acpi_os_name_setup(char *str)
 
 __setup("acpi_os_name=", acpi_os_name_setup);
 
+#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
+#define        OSI_STRING_ENTRIES_MAX 16       /* arbitrary */
+
+struct osi_setup_entry {
+       char string[OSI_STRING_LENGTH_MAX];
+       bool enable;
+};
+
+static struct osi_setup_entry __initdata osi_setup_entries[OSI_STRING_ENTRIES_MAX];
+
+void __init acpi_osi_setup(char *str)
+{
+       struct osi_setup_entry *osi;
+       bool enable = true;
+       int i;
+
+       if (!acpi_gbl_create_osi_method)
+               return;
+
+       if (str == NULL || *str == '\0') {
+               printk(KERN_INFO PREFIX "_OSI method disabled\n");
+               acpi_gbl_create_osi_method = FALSE;
+               return;
+       }
+
+       if (*str == '!') {
+               str++;
+               enable = false;
+       }
+
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               if (!strcmp(osi->string, str)) {
+                       osi->enable = enable;
+                       break;
+               } else if (osi->string[0] == '\0') {
+                       osi->enable = enable;
+                       strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
+                       break;
+               }
+       }
+}
+
 static void __init set_osi_linux(unsigned int enable)
 {
-       if (osi_linux.enable != enable) {
+       if (osi_linux.enable != enable)
                osi_linux.enable = enable;
-               printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
-                       enable ? "Add": "Delet");
-       }
 
        if (osi_linux.enable)
                acpi_osi_setup("Linux");
@@ -1073,7 +1109,8 @@ static void __init set_osi_linux(unsigned int enable)
 
 static void __init acpi_cmdline_osi_linux(unsigned int enable)
 {
-       osi_linux.cmdline = 1;  /* cmdline set the default */
+       osi_linux.cmdline = 1;  /* cmdline set the default and override DMI */
+       osi_linux.dmi = 0;
        set_osi_linux(enable);
 
        return;
@@ -1081,15 +1118,12 @@ static void __init acpi_cmdline_osi_linux(unsigned int enable)
 
 void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
 {
-       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
-
        printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
 
        if (enable == -1)
                return;
 
-       osi_linux.known = 1;    /* DMI knows which OSI(Linux) default needed */
-
+       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
        set_osi_linux(enable);
 
        return;
@@ -1104,37 +1138,44 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
  */
 static void __init acpi_osi_setup_late(void)
 {
-       char *str = osi_setup_string;
+       struct osi_setup_entry *osi;
+       char *str;
+       int i;
+       acpi_status status;
 
-       if (*str == '\0')
-               return;
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               str = osi->string;
 
-       if (!strcmp("!Linux", str)) {
-               acpi_cmdline_osi_linux(0);      /* !enable */
-       } else if (*str == '!') {
-               if (acpi_remove_interface(++str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
-       } else if (!strcmp("Linux", str)) {
-               acpi_cmdline_osi_linux(1);      /* enable */
-       } else {
-               if (acpi_install_interface(str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               if (*str == '\0')
+                       break;
+               if (osi->enable) {
+                       status = acpi_install_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               } else {
+                       status = acpi_remove_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
+               }
        }
 }
 
-int __init acpi_osi_setup(char *str)
+static int __init osi_setup(char *str)
 {
-       if (str == NULL || *str == '\0') {
-               printk(KERN_INFO PREFIX "_OSI method disabled\n");
-               acpi_gbl_create_osi_method = FALSE;
-       } else {
-               strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
-       }
+       if (str && !strcmp("Linux", str))
+               acpi_cmdline_osi_linux(1);
+       else if (str && !strcmp("!Linux", str))
+               acpi_cmdline_osi_linux(0);
+       else
+               acpi_osi_setup(str);
 
        return 1;
 }
 
-__setup("acpi_osi=", acpi_osi_setup);
+__setup("acpi_osi=", osi_setup);
 
 /* enable serialization to combat AE_ALREADY_EXISTS errors */
 static int __init acpi_serialize_setup(char *str)
@@ -1530,7 +1571,7 @@ acpi_status __init acpi_os_initialize(void)
        return AE_OK;
 }
 
-acpi_status acpi_os_initialize1(void)
+acpi_status __init acpi_os_initialize1(void)
 {
        kacpid_wq = create_workqueue("kacpid");
        kacpi_notify_wq = create_workqueue("kacpi_notify");
index 67dedeed144cf82c8e13859e7222b976d0eebb2e..4c9c2fb5d98f9a14a67e8618b44dc6f2c642887b 100644 (file)
@@ -213,11 +213,13 @@ static int acpi_power_on(acpi_handle handle)
                                  resource->name));
        } else {
                result = __acpi_power_on(resource);
+               if (result)
+                       resource->ref_count--;
        }
 
        mutex_unlock(&resource->resource_lock);
 
-       return 0;
+       return result;
 }
 
 static int acpi_power_off_device(acpi_handle handle)
@@ -465,10 +467,12 @@ int acpi_power_transition(struct acpi_device *device, int state)
        struct acpi_handle_list *tl = NULL;     /* Target Resources */
        int i = 0;
 
-
        if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
                return -EINVAL;
 
+       if (device->power.state == state)
+               return 0;
+
        if ((device->power.state < ACPI_STATE_D0)
            || (device->power.state > ACPI_STATE_D3))
                return -ENODEV;
@@ -488,10 +492,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
                        goto end;
        }
 
-       if (device->power.state == state) {
-               goto end;
-       }
-
        /*
         * Then we dereference all power resources used in the current list.
         */
index fde49b9b1d99ed04eaf4192473ff7ce3bb913fd6..79cb6533289456c4f43b92dda5d7059a27345afa 100644 (file)
@@ -156,15 +156,6 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
        return 0;
 }
 
-static int acpi_thermal_cpufreq_increase(unsigned int cpu)
-{
-       return -ENODEV;
-}
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
-{
-       return -ENODEV;
-}
-
 #endif
 
 int acpi_processor_get_limit_info(struct acpi_processor *pr)
index 721d93b3ceee78c3b271f5f84ffe4fc795e435e1..febb153b5a68cf216fdd1b528ac44159e73abcba 100644 (file)
@@ -27,8 +27,6 @@
 
 static u8 sleep_states[ACPI_S_STATE_COUNT];
 
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
        union acpi_object in_arg = { ACPI_TYPE_INTEGER };
@@ -81,6 +79,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
 }
 
 #ifdef CONFIG_ACPI_SLEEP
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
 /*
  * The ACPI specification wants us to save NVS memory regions during hibernation
  * and to restore them during the subsequent resume.  Windows does that also for
@@ -427,6 +427,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
                },
        },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-NW130D",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
index 46b94762125b0b179792948cbd47be8a9bc8448f..f9b983ae68777544f5cc986f3e0e4e3b1f074179 100644 (file)
@@ -154,7 +154,7 @@ static int __init adummy_init(void)
                err = -ENOMEM;
                goto out;
        }
-       atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, NULL);
+       atm_dev = atm_dev_register(DEV_LABEL, NULL, &adummy_ops, -1, NULL);
        if (!atm_dev) {
                printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n");
                err = -ENODEV;
index a33896a482e6eb0e0dd964649b5b6d7d90e64858..ffe9b655292e148e929365fe5bd8cd1b86443411 100644 (file)
@@ -2244,7 +2244,8 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_
                goto out_reset;
        }
 
-       dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, NULL);
+       dev->atm_dev = atm_dev_register (DEV_LABEL, &pci_dev->dev, &amb_ops, -1,
+                                        NULL);
        if (!dev->atm_dev) {
                PRINTD (DBG_ERR, "failed to register Madge ATM adapter");
                err = -EINVAL;
index b9101818b47b4012d9c5589d7b8ffd672cb26fc7..2b464b631f22697ac5f177d371b94d5646683d8f 100644 (file)
@@ -366,7 +366,7 @@ static int atmtcp_create(int itf,int persist,struct atm_dev **result)
        if (!dev_data)
                return -ENOMEM;
 
-       dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
+       dev = atm_dev_register(DEV_LABEL,NULL,&atmtcp_v_dev_ops,itf,NULL);
        if (!dev) {
                kfree(dev_data);
                return itf == -1 ? -ENOMEM : -EBUSY;
index 97c5898cd76e894350dfcc3a444de9ce2d202e35..c495fae742008c6569da47d5c3ca91c7f5ad48b4 100644 (file)
@@ -2244,7 +2244,7 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
                    &zeroes);
                if (!cpu_zeroes) goto out1;
        }
-       dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);
+       dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
        if (!dev) goto out2;
        pci_set_drvdata(pci_dev, dev);
        eni_dev->pci_dev = pci_dev;
index 5d86bb803e9493443659f49180b68c147066a166..7d912baf01d444c6adaaa943f87e107ead7441b6 100644 (file)
@@ -1911,7 +1911,7 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev,
                    fs_dev, sizeof (struct fs_dev));
        if (!fs_dev)
                goto err_out;
-       atm_dev = atm_dev_register("fs", &ops, -1, NULL);
+       atm_dev = atm_dev_register("fs", &pci_dev->dev, &ops, -1, NULL);
        if (!atm_dev)
                goto err_out_free_fs_dev;
   
index c8fc69c85a062f81029495e827ae615547f964e9..962c309b40c035bea03e751fd9531de6eb7df1e9 100644 (file)
@@ -2567,14 +2567,14 @@ release:
 
 
 static int __devinit
-fore200e_register(struct fore200e* fore200e)
+fore200e_register(struct fore200e* fore200e, struct device *parent)
 {
     struct atm_dev* atm_dev;
 
     DPRINTK(2, "device %s being registered\n", fore200e->name);
 
-    atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1,
-      NULL); 
+    atm_dev = atm_dev_register(fore200e->bus->proc_name, parent, &fore200e_ops,
+                               -1, NULL);
     if (atm_dev == NULL) {
        printk(FORE200E "unable to register device %s\n", fore200e->name);
        return -ENODEV;
@@ -2594,9 +2594,9 @@ fore200e_register(struct fore200e* fore200e)
 
 
 static int __devinit
-fore200e_init(struct fore200e* fore200e)
+fore200e_init(struct fore200e* fore200e, struct device *parent)
 {
-    if (fore200e_register(fore200e) < 0)
+    if (fore200e_register(fore200e, parent) < 0)
        return -ENODEV;
     
     if (fore200e->bus->configure(fore200e) < 0)
@@ -2662,7 +2662,7 @@ static int __devinit fore200e_sba_probe(struct platform_device *op,
 
        sprintf(fore200e->name, "%s-%d", bus->model_name, index);
 
-       err = fore200e_init(fore200e);
+       err = fore200e_init(fore200e, &op->dev);
        if (err < 0) {
                fore200e_shutdown(fore200e);
                kfree(fore200e);
@@ -2740,7 +2740,7 @@ fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent
 
     sprintf(fore200e->name, "%s-%d", bus->model_name, index);
 
-    err = fore200e_init(fore200e);
+    err = fore200e_init(fore200e, &pci_dev->dev);
     if (err < 0) {
        fore200e_shutdown(fore200e);
        goto out_free;
index 801e8b6e9d1fee08dd1b3d091ff3739193ee98cc..6cf59bf281dc1b601884586b7d8651ea0ecbeaa7 100644 (file)
@@ -366,7 +366,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
                goto init_one_failure;
        }
 
-       atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, NULL);
+       atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &he_ops, -1, NULL);
        if (!atm_dev) {
                err = -ENODEV;
                goto init_one_failure;
index a95790452a685f3325ed64af5db2f2596f911236..24761e1d6642d7c6a2c7dcb6e8d4073c89f76c64 100644 (file)
@@ -2733,7 +2733,8 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_
        PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
               iobase, irq, membase);
 
-       dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL);
+       dev->atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &hrz_ops, -1,
+                                       NULL);
        if (!(dev->atm_dev)) {
                PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
                err = -EINVAL;
index bce57328ddde9addf376fe550a768194c4173c9b..bfb7feee0400df5c8f9a13adc0cde06a053c2ac7 100644 (file)
@@ -3698,7 +3698,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                goto err_out_iounmap;
        }
 
-       dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL);
+       dev = atm_dev_register("idt77252", &pcidev->dev, &idt77252_ops, -1,
+                              NULL);
        if (!dev) {
                printk("%s: can't register atm device\n", card->name);
                err = -EIO;
index 9309d4724e1322effe4010042dc0a3136a432ebb..729254053758f0d3680ad67f52a32a07865f86b0 100644 (file)
@@ -3172,7 +3172,7 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
                ret = -ENODEV;
                goto err_out_free_iadev;
        }
-       dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       dev = atm_dev_register(DEV_LABEL, &pdev->dev, &ops, -1, NULL);
        if (!dev) {
                ret = -ENOMEM;
                goto err_out_disable_dev;
index cbe15a86c6698b2044b45469fa57f8d199aca15e..a395c9aab146ec4f78d0b05767c81b04889c16ef 100644 (file)
@@ -2591,7 +2591,7 @@ static int __devinit lanai_init_one(struct pci_dev *pci,
                return -ENOMEM;
        }
 
-       atmdev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       atmdev = atm_dev_register(DEV_LABEL, &pci->dev, &ops, -1, NULL);
        if (atmdev == NULL) {
                printk(KERN_ERR DEV_LABEL
                    ": couldn't register atm device!\n");
index 2f3516b7f118cd59e7b9156ba1b004a6caee6c86..6b313ee9231baa2cd37893ba26c5e4877462ba0a 100644 (file)
@@ -771,7 +771,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
        }
 
        /* Register device */
-       card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL);
+       card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops,
+                                       -1, NULL);
        if (card->atmdev == NULL) {
                printk("nicstar%d: can't register device.\n", i);
                error = 17;
index 2e08c996fd30a6156e8a0a19e46966824d3d89df..73fb1c4f4cd4e99f0b57df7977c22216a781e1e6 100644 (file)
@@ -166,7 +166,7 @@ static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
 static int list_vccs(int vci);
 static void release_vccs(struct atm_dev *dev);
-static int atm_init(struct solos_card *);
+static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
 static void solos_bh(unsigned long);
@@ -1210,7 +1210,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (db_firmware_upgrade)
                flash_upgrade(card, 3);
 
-       err = atm_init(card);
+       err = atm_init(card, &dev->dev);
        if (err)
                goto out_free_irq;
 
@@ -1233,7 +1233,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        return err;
 }
 
-static int atm_init(struct solos_card *card)
+static int atm_init(struct solos_card *card, struct device *parent)
 {
        int i;
 
@@ -1244,7 +1244,7 @@ static int atm_init(struct solos_card *card)
                skb_queue_head_init(&card->tx_queue[i]);
                skb_queue_head_init(&card->cli_queue[i]);
 
-               card->atmdev[i] = atm_dev_register("solos-pci", &fpga_ops, -1, NULL);
+               card->atmdev[i] = atm_dev_register("solos-pci", parent, &fpga_ops, -1, NULL);
                if (!card->atmdev[i]) {
                        dev_err(&card->dev->dev, "Could not register ATM device %d\n", i);
                        atm_remove(card);
index 4e885d2da49c6f0b5899b9eb3d8d1a874e700ca3..624917902b656f249fd06b057090f0f9d7b97961 100644 (file)
@@ -1597,7 +1597,7 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev,
                goto out;
        }
 
-       dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+       dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
        if (!dev)
                goto out_free;
 
index 4f9e22f29138f1001dfca566ab3b04e176b6ae2e..657873e4328dbf05421b80e8d1231f27c5d3b369 100644 (file)
@@ -72,7 +72,7 @@ struct blk_shadow {
 static DEFINE_MUTEX(blkfront_mutex);
 static const struct block_device_operations xlvbd_block_fops;
 
-#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
+#define BLK_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE)
 
 /*
  * We have one of these per vbd, whether ide, scsi or 'other'.  They
index 128cae4e8629465429cf271209f587b8e192b3ad..949ed09c6361130c30c3ebda1bc4db02b00fa4c2 100644 (file)
 static struct usb_device_id ath3k_table[] = {
        /* Atheros AR3011 */
        { USB_DEVICE(0x0CF3, 0x3000) },
+
+       /* Atheros AR3011 with sflash firmware*/
+       { USB_DEVICE(0x0CF3, 0x3002) },
+
        { }     /* Terminating entry */
 };
 
index ab3894f742c3002a90a98b89f116ab30c75cdb28..1da773f899a2708f1c151b892098ed3ddbaf79cf 100644 (file)
@@ -99,6 +99,9 @@ static struct usb_device_id blacklist_table[] = {
        /* Broadcom BCM2033 without firmware */
        { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
 
+       /* Atheros 3011 with sflash firmware */
+       { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
+
        /* Broadcom BCM2035 */
        { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
        { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -239,7 +242,8 @@ static void btusb_intr_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
@@ -323,7 +327,8 @@ static void btusb_bulk_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
@@ -412,7 +417,8 @@ static void btusb_isoc_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               BT_ERR("%s urb %p failed to resubmit (%d)",
+               if (err != -EPERM)
+                       BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
index 9272c38dd3c6ce8a66e9e0d2b0a5085ddd2973a7..16a2847b7cdbfeee43c9dcd212915a2f6b500711 100644 (file)
@@ -812,8 +812,10 @@ static int intel_fake_agp_fetch_size(void)
 
 static void i830_cleanup(void)
 {
-       kunmap(intel_private.i8xx_page);
-       intel_private.i8xx_flush_page = NULL;
+       if (intel_private.i8xx_flush_page) {
+               kunmap(intel_private.i8xx_flush_page);
+               intel_private.i8xx_flush_page = NULL;
+       }
 
        __free_page(intel_private.i8xx_page);
        intel_private.i8xx_page = NULL;
index e16c3fa8d2e3e3649a6cab79fb34db9323aae711..05117f1ad8674839331ddb7c473b4cfc739bbddd 100644 (file)
@@ -36,6 +36,7 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_CONNECTOR);
 
 static struct cn_dev cdev;
 
index a8a84f4587f20d7437af9ce12932dbf8e92a4e1b..64b21f5cd740fc5dfa1d5f09b1a944ed1f661440 100644 (file)
@@ -1,8 +1,8 @@
 ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
-       EXTRA_CFLAGS    += -DDEBUG
+       ccflags-y       += -DDEBUG
 endif
 ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
-       EXTRA_CFLAGS    += -DVERBOSE_DEBUG
+       ccflags-y       += -DVERBOSE_DEBUG
 endif
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
index a0f3e6a06e06532b3701ade73b110d823eec591f..ea0ee81cff53e266643140eb752ef3ba26289c6a 100644 (file)
@@ -722,7 +722,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        desc->lli.daddr = mem;
                        desc->lli.ctrla = ctrla
                                        | ATC_DST_WIDTH(mem_width)
-                                       | len >> mem_width;
+                                       | len >> reg_width;
                        desc->lli.ctrlb = ctrlb;
 
                        if (!first) {
index 286c3ac6bdcc236d020229ce0397ee9e78e07100..e5e172d21692d60a81fce6a9ed06e5807c57b370 100644 (file)
@@ -50,9 +50,11 @@ static void dma_init(struct fsldma_chan *chan)
                 * EIE - Error interrupt enable
                 * EOSIE - End of segments interrupt enable (basic mode)
                 * EOLNIE - End of links interrupt enable
+                * BWC - Bandwidth sharing among channels
                 */
-               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EIE
-                               | FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
+               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+                               | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
+                               | FSL_DMA_MR_EOSIE, 32);
                break;
        case FSL_DMA_IP_83XX:
                /* Set the channel to below modes:
index cb4d6ff5159766baf7dce594dca6fb57e3d28dd2..ba9f403c0fbe9127441e7b92bf70c59c71cbde28 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author:
  *   Zhang Wei <wei.zhang@freescale.com>, Jul 2007
 #define FSL_DMA_MR_DAHE                0x00002000
 #define FSL_DMA_MR_SAHE                0x00001000
 
+/*
+ * Bandwidth/pause control determines how many bytes a given
+ * channel is allowed to transfer before the DMA engine pauses
+ * the current channel and switches to the next channel
+ */
+#define FSL_DMA_MR_BWC         0x08000000
+
 /* Special MR definition for MPC8349 */
 #define FSL_DMA_MR_EOTIE       0x00000080
 #define FSL_DMA_MR_PRC_RM      0x00000800
index f629e4961af593f0ab5d3697fce77b306ab1ed9b..e53d438142bb8747cb8f288e64d75b0ba2e18a97 100644 (file)
@@ -379,7 +379,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
        return 0;
 
 err_init:
-       while (i-- >= 0) {
+       while (--i >= 0) {
                struct imxdma_channel *imxdmac = &imxdma->channel[i];
                imx_dma_free(imxdmac->imxdma_channel);
        }
index 01166a9c32417bd3736b520571ac5017d1f2d2f7..d5a5d4d9c19bb9efc3dd084e2961fd99d1d098f6 100644 (file)
@@ -907,7 +907,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
                int param;
 
-               bd->buffer_addr = sgl->dma_address;
+               bd->buffer_addr = sg->dma_address;
 
                count = sg->length;
 
@@ -1367,7 +1367,7 @@ static int __init sdma_module_init(void)
 {
        return platform_driver_probe(&sdma_driver, sdma_probe);
 }
-subsys_initcall(sdma_module_init);
+module_init(sdma_module_init);
 
 MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX SDMA driver");
index 338bc4eed1f3f55b4de66c623a135289862c783f..3109bd94bc4f403c5aba44e8ff7cb092aa23b4cd 100644 (file)
@@ -1075,7 +1075,6 @@ static int mid_setup_dma(struct pci_dev *pdev)
        if (NULL == dma->dma_pool) {
                pr_err("ERR_MDMA:pci_pool_create failed\n");
                err = -ENOMEM;
-               kfree(dma);
                goto err_dma_pool;
        }
 
@@ -1186,7 +1185,6 @@ err_engine:
        free_irq(pdev->irq, dma);
 err_irq:
        pci_pool_destroy(dma->dma_pool);
-       kfree(dma);
 err_dma_pool:
        pr_err("ERR_MDMA:setup_dma failed: %d\n", err);
        return err;
@@ -1413,7 +1411,7 @@ static const struct dev_pm_ops intel_mid_dma_pm = {
        .runtime_idle = dma_runtime_idle,
 };
 
-static struct pci_driver intel_mid_dma_pci = {
+static struct pci_driver intel_mid_dma_pci_driver = {
        .name           =       "Intel MID DMA",
        .id_table       =       intel_mid_dma_ids,
        .probe          =       intel_mid_dma_probe,
@@ -1431,13 +1429,13 @@ static int __init intel_mid_dma_init(void)
 {
        pr_debug("INFO_MDMA: LNW DMA Driver Version %s\n",
                        INTEL_MID_DMA_DRIVER_VERSION);
-       return pci_register_driver(&intel_mid_dma_pci);
+       return pci_register_driver(&intel_mid_dma_pci_driver);
 }
 fs_initcall(intel_mid_dma_init);
 
 static void __exit intel_mid_dma_exit(void)
 {
-       pci_unregister_driver(&intel_mid_dma_pci);
+       pci_unregister_driver(&intel_mid_dma_pci_driver);
 }
 module_exit(intel_mid_dma_exit);
 
index 8997d3fb9051db0020bbeb721cc5a562d780bf47..0ff7270af25b97800d64fcc6f62c350f3115f322 100644 (file)
@@ -1,2 +1,2 @@
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
-ioatdma-objs := pci.o dma.o dma_v2.o dma_v3.o dca.o
+ioatdma-y := pci.o dma.o dma_v2.o dma_v3.o dca.o
index 92b679024fedd9e033e9cbae311f7f8d7f221142..c064c89420d06080a737ea48356501aeeae869cd 100644 (file)
@@ -259,11 +259,6 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
                return;
        }
 
-       channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
-       channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
-       channel_writel(pd_chan, SIZE, desc->regs.size);
-       channel_writel(pd_chan, NEXT, desc->regs.next);
-
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> dev_addr: %x\n",
                pd_chan->chan.chan_id, desc->regs.dev_addr);
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> mem_addr: %x\n",
@@ -273,10 +268,16 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> next: %x\n",
                pd_chan->chan.chan_id, desc->regs.next);
 
-       if (list_empty(&desc->tx_list))
+       if (list_empty(&desc->tx_list)) {
+               channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
+               channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
+               channel_writel(pd_chan, SIZE, desc->regs.size);
+               channel_writel(pd_chan, NEXT, desc->regs.next);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_ONESHOT);
-       else
+       } else {
+               channel_writel(pd_chan, NEXT, desc->txd.phys);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_SG);
+       }
 
        val = dma_readl(pd, CTL2);
        val |= 1 << (DMA_CTL2_START_SHIFT_BITS + pd_chan->chan.chan_id);
index 0d58a4a4487fbbaefc167182a627c6b0b0f222b3..cef584533ee8a9ca5628b874b5d6c644a4ad05f4 100644 (file)
@@ -4449,9 +4449,8 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev,
 
        if (!request_mem_region(res.start, resource_size(&res),
                                dev_driver_string(&ofdev->dev))) {
-               dev_err(&ofdev->dev, "failed to request memory region "
-                       "(0x%016llx-0x%016llx)\n",
-                       (u64)res.start, (u64)res.end);
+               dev_err(&ofdev->dev, "failed to request memory region %pR\n",
+                       &res);
                initcode = PPC_ADMA_INIT_MEMREG;
                ret = -EBUSY;
                goto out;
index 8521401bbd751406e6f2752e10868f63c7e3b48a..eca9ba193e94a914aa64740f0b4262b8f7c99b81 100644 (file)
@@ -1572,7 +1572,7 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
        debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
                        hole_off, hole_valid, intlv_sel);
 
-       if (intlv_en ||
+       if (intlv_en &&
            (intlv_sel != ((sys_addr >> 12) & intlv_en)))
                return -EINVAL;
 
index d7ca43a828bd3fe57b3de1341d7e75d1bed84f0a..251440cd50a3b41ea47f4511365909b707ebf0e8 100644 (file)
 #define MC_PROC_NAME_MAX_LEN   7
 
 #if PAGE_SHIFT < 20
-#define PAGES_TO_MiB( pages )  ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
-#define MiB_TO_PAGES(mb)       ((mb) >> (20 - PAGE_SHIFT))
+#define PAGES_TO_MiB(pages)    ((pages) >> (20 - PAGE_SHIFT))
+#define MiB_TO_PAGES(mb)       ((mb) << (20 - PAGE_SHIFT))
 #else                          /* PAGE_SHIFT > 20 */
-#define PAGES_TO_MiB( pages )  ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#define PAGES_TO_MiB(pages)    ((pages) << (PAGE_SHIFT - 20))
 #define MiB_TO_PAGES(mb)       ((mb) >> (PAGE_SHIFT - 20))
 #endif
 
index ba6586a69ccce3b000fb22ee21512ab4673b44ac..795ea69c4d8f5fb6149c62fba8e085bd83363309 100644 (file)
@@ -586,14 +586,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
                return NULL;
        }
 
-       /* marking MCI offline */
-       mci->op_state = OP_OFFLINE;
-
        del_mc_from_global_list(mci);
        mutex_unlock(&mem_ctls_mutex);
 
-       /* flush workq processes and remove sysfs */
+       /* flush workq processes */
        edac_mc_workq_teardown(mci);
+
+       /* marking MCI offline */
+       mci->op_state = OP_OFFLINE;
+
+       /* remove from sysfs */
        edac_remove_sysfs_mci_device(mci);
 
        edac_printk(KERN_INFO, EDAC_MC,
index 84eb607d6c031b4275e834604d4c0c0729fa8502..e3c8b60bd86be8873e781bef053f466898be16c2 100644 (file)
@@ -242,6 +242,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
+#define PCI_DEVICE_ID_AGERE_FW643      0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
 
@@ -253,18 +254,34 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
-       unsigned short vendor, device, flags;
+       unsigned short vendor, device, revision, flags;
 } ohci_quirks[] = {
-       {PCI_VENDOR_ID_TI,      PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
-                                                           QUIRK_RESET_PACKET |
-                                                           QUIRK_NO_1394A},
-       {PCI_VENDOR_ID_TI,      PCI_ANY_ID,     QUIRK_RESET_PACKET},
-       {PCI_VENDOR_ID_AL,      PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
-       {PCI_VENDOR_ID_NEC,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_VIA,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_RICOH,   PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_APPLE,   PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
+       {PCI_VENDOR_ID_AL, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, PCI_ANY_ID,
+               QUIRK_BE_HEADERS},
+
+       {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_NEC, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
+
+       {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_RESET_PACKET},
+
+       {PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
 };
 
 /* This overrides anything that was found in ohci_quirks[]. */
@@ -2927,9 +2944,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
        }
 
        for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++)
-               if (ohci_quirks[i].vendor == dev->vendor &&
-                   (ohci_quirks[i].device == dev->device ||
-                    ohci_quirks[i].device == (unsigned short)PCI_ANY_ID)) {
+               if ((ohci_quirks[i].vendor == dev->vendor) &&
+                   (ohci_quirks[i].device == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].device == dev->device) &&
+                   (ohci_quirks[i].revision == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].revision >= dev->revision)) {
                        ohci->quirks = ohci_quirks[i].flags;
                        break;
                }
index 3143ac795eb0c4d7031fc21b5e3d0ff476bca8ce..082495bb08a7064c9a8d37dc1dec96242d747d2f 100644 (file)
@@ -230,11 +230,11 @@ config GPIO_STMPE
          This enables support for the GPIOs found on the STMPE I/O
          Expanders.
 
-config GPIO_TC35892
-       bool "TC35892 GPIOs"
-       depends on MFD_TC35892
+config GPIO_TC3589X
+       bool "TC3589X GPIOs"
+       depends on MFD_TC3589X
        help
-         This enables support for the GPIOs found on the TC35892
+         This enables support for the GPIOs found on the TC3589X
          I/O Expander.
 
 config GPIO_TWL4030
index bdf3ddec06528074aa5953a8e0244805b799f5d5..39bfd7a37650992b12456c33f3300b203e40dd60 100644 (file)
@@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_PCF857X)    += pcf857x.o
 obj-$(CONFIG_GPIO_PCH)         += pch_gpio.o
 obj-$(CONFIG_GPIO_PL061)       += pl061.o
 obj-$(CONFIG_GPIO_STMPE)       += stmpe-gpio.o
-obj-$(CONFIG_GPIO_TC35892)     += tc35892-gpio.o
+obj-$(CONFIG_GPIO_TC3589X)     += tc3589x-gpio.o
 obj-$(CONFIG_GPIO_TIMBERDALE)  += timbgpio.o
 obj-$(CONFIG_GPIO_TWL4030)     += twl4030-gpio.o
 obj-$(CONFIG_GPIO_UCB1400)     += ucb1400_gpio.o
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c
deleted file mode 100644 (file)
index 7e10c93..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/tc35892.h>
-
-/*
- * These registers are modified under the irq bus lock and cached to avoid
- * unnecessary writes in bus_sync_unlock.
- */
-enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
-
-#define CACHE_NR_REGS  4
-#define CACHE_NR_BANKS 3
-
-struct tc35892_gpio {
-       struct gpio_chip chip;
-       struct tc35892 *tc35892;
-       struct device *dev;
-       struct mutex irq_lock;
-
-       int irq_base;
-
-       /* Caches of interrupt control registers for bus_lock */
-       u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
-       u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
-};
-
-static inline struct tc35892_gpio *to_tc35892_gpio(struct gpio_chip *chip)
-{
-       return container_of(chip, struct tc35892_gpio, chip);
-}
-
-static int tc35892_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-       u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
-       u8 mask = 1 << (offset % 8);
-       int ret;
-
-       ret = tc35892_reg_read(tc35892, reg);
-       if (ret < 0)
-               return ret;
-
-       return ret & mask;
-}
-
-static void tc35892_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-       u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
-       unsigned pos = offset % 8;
-       u8 data[] = {!!val << pos, 1 << pos};
-
-       tc35892_block_write(tc35892, reg, ARRAY_SIZE(data), data);
-}
-
-static int tc35892_gpio_direction_output(struct gpio_chip *chip,
-                                        unsigned offset, int val)
-{
-       struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-       u8 reg = TC35892_GPIODIR0 + offset / 8;
-       unsigned pos = offset % 8;
-
-       tc35892_gpio_set(chip, offset, val);
-
-       return tc35892_set_bits(tc35892, reg, 1 << pos, 1 << pos);
-}
-
-static int tc35892_gpio_direction_input(struct gpio_chip *chip,
-                                       unsigned offset)
-{
-       struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-       u8 reg = TC35892_GPIODIR0 + offset / 8;
-       unsigned pos = offset % 8;
-
-       return tc35892_set_bits(tc35892, reg, 1 << pos, 0);
-}
-
-static int tc35892_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
-
-       return tc35892_gpio->irq_base + offset;
-}
-
-static struct gpio_chip template_chip = {
-       .label                  = "tc35892",
-       .owner                  = THIS_MODULE,
-       .direction_input        = tc35892_gpio_direction_input,
-       .get                    = tc35892_gpio_get,
-       .direction_output       = tc35892_gpio_direction_output,
-       .set                    = tc35892_gpio_set,
-       .to_irq                 = tc35892_gpio_to_irq,
-       .can_sleep              = 1,
-};
-
-static int tc35892_gpio_irq_set_type(unsigned int irq, unsigned int type)
-{
-       struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-       int offset = irq - tc35892_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       if (type == IRQ_TYPE_EDGE_BOTH) {
-               tc35892_gpio->regs[REG_IBE][regoffset] |= mask;
-               return 0;
-       }
-
-       tc35892_gpio->regs[REG_IBE][regoffset] &= ~mask;
-
-       if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
-               tc35892_gpio->regs[REG_IS][regoffset] |= mask;
-       else
-               tc35892_gpio->regs[REG_IS][regoffset] &= ~mask;
-
-       if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
-               tc35892_gpio->regs[REG_IEV][regoffset] |= mask;
-       else
-               tc35892_gpio->regs[REG_IEV][regoffset] &= ~mask;
-
-       return 0;
-}
-
-static void tc35892_gpio_irq_lock(unsigned int irq)
-{
-       struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-
-       mutex_lock(&tc35892_gpio->irq_lock);
-}
-
-static void tc35892_gpio_irq_sync_unlock(unsigned int irq)
-{
-       struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-       static const u8 regmap[] = {
-               [REG_IBE]       = TC35892_GPIOIBE0,
-               [REG_IEV]       = TC35892_GPIOIEV0,
-               [REG_IS]        = TC35892_GPIOIS0,
-               [REG_IE]        = TC35892_GPIOIE0,
-       };
-       int i, j;
-
-       for (i = 0; i < CACHE_NR_REGS; i++) {
-               for (j = 0; j < CACHE_NR_BANKS; j++) {
-                       u8 old = tc35892_gpio->oldregs[i][j];
-                       u8 new = tc35892_gpio->regs[i][j];
-
-                       if (new == old)
-                               continue;
-
-                       tc35892_gpio->oldregs[i][j] = new;
-                       tc35892_reg_write(tc35892, regmap[i] + j * 8, new);
-               }
-       }
-
-       mutex_unlock(&tc35892_gpio->irq_lock);
-}
-
-static void tc35892_gpio_irq_mask(unsigned int irq)
-{
-       struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-       int offset = irq - tc35892_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       tc35892_gpio->regs[REG_IE][regoffset] &= ~mask;
-}
-
-static void tc35892_gpio_irq_unmask(unsigned int irq)
-{
-       struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
-       int offset = irq - tc35892_gpio->irq_base;
-       int regoffset = offset / 8;
-       int mask = 1 << (offset % 8);
-
-       tc35892_gpio->regs[REG_IE][regoffset] |= mask;
-}
-
-static struct irq_chip tc35892_gpio_irq_chip = {
-       .name                   = "tc35892-gpio",
-       .bus_lock               = tc35892_gpio_irq_lock,
-       .bus_sync_unlock        = tc35892_gpio_irq_sync_unlock,
-       .mask                   = tc35892_gpio_irq_mask,
-       .unmask                 = tc35892_gpio_irq_unmask,
-       .set_type               = tc35892_gpio_irq_set_type,
-};
-
-static irqreturn_t tc35892_gpio_irq(int irq, void *dev)
-{
-       struct tc35892_gpio *tc35892_gpio = dev;
-       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-       u8 status[CACHE_NR_BANKS];
-       int ret;
-       int i;
-
-       ret = tc35892_block_read(tc35892, TC35892_GPIOMIS0,
-                                ARRAY_SIZE(status), status);
-       if (ret < 0)
-               return IRQ_NONE;
-
-       for (i = 0; i < ARRAY_SIZE(status); i++) {
-               unsigned int stat = status[i];
-               if (!stat)
-                       continue;
-
-               while (stat) {
-                       int bit = __ffs(stat);
-                       int line = i * 8 + bit;
-
-                       handle_nested_irq(tc35892_gpio->irq_base + line);
-                       stat &= ~(1 << bit);
-               }
-
-               tc35892_reg_write(tc35892, TC35892_GPIOIC0 + i, status[i]);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio)
-{
-       int base = tc35892_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
-               set_irq_chip_data(irq, tc35892_gpio);
-               set_irq_chip_and_handler(irq, &tc35892_gpio_irq_chip,
-                                        handle_simple_irq);
-               set_irq_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               set_irq_noprobe(irq);
-#endif
-       }
-
-       return 0;
-}
-
-static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio)
-{
-       int base = tc35892_gpio->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, 0);
-#endif
-               set_irq_chip_and_handler(irq, NULL, NULL);
-               set_irq_chip_data(irq, NULL);
-       }
-}
-
-static int __devinit tc35892_gpio_probe(struct platform_device *pdev)
-{
-       struct tc35892 *tc35892 = dev_get_drvdata(pdev->dev.parent);
-       struct tc35892_gpio_platform_data *pdata;
-       struct tc35892_gpio *tc35892_gpio;
-       int ret;
-       int irq;
-
-       pdata = tc35892->pdata->gpio;
-       if (!pdata)
-               return -ENODEV;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       tc35892_gpio = kzalloc(sizeof(struct tc35892_gpio), GFP_KERNEL);
-       if (!tc35892_gpio)
-               return -ENOMEM;
-
-       mutex_init(&tc35892_gpio->irq_lock);
-
-       tc35892_gpio->dev = &pdev->dev;
-       tc35892_gpio->tc35892 = tc35892;
-
-       tc35892_gpio->chip = template_chip;
-       tc35892_gpio->chip.ngpio = tc35892->num_gpio;
-       tc35892_gpio->chip.dev = &pdev->dev;
-       tc35892_gpio->chip.base = pdata->gpio_base;
-
-       tc35892_gpio->irq_base = tc35892->irq_base + TC35892_INT_GPIO(0);
-
-       /* Bring the GPIO module out of reset */
-       ret = tc35892_set_bits(tc35892, TC35892_RSTCTRL,
-                              TC35892_RSTCTRL_GPIRST, 0);
-       if (ret < 0)
-               goto out_free;
-
-       ret = tc35892_gpio_irq_init(tc35892_gpio);
-       if (ret)
-               goto out_free;
-
-       ret = request_threaded_irq(irq, NULL, tc35892_gpio_irq, IRQF_ONESHOT,
-                                  "tc35892-gpio", tc35892_gpio);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-               goto out_removeirq;
-       }
-
-       ret = gpiochip_add(&tc35892_gpio->chip);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-               goto out_freeirq;
-       }
-
-       if (pdata->setup)
-               pdata->setup(tc35892, tc35892_gpio->chip.base);
-
-       platform_set_drvdata(pdev, tc35892_gpio);
-
-       return 0;
-
-out_freeirq:
-       free_irq(irq, tc35892_gpio);
-out_removeirq:
-       tc35892_gpio_irq_remove(tc35892_gpio);
-out_free:
-       kfree(tc35892_gpio);
-       return ret;
-}
-
-static int __devexit tc35892_gpio_remove(struct platform_device *pdev)
-{
-       struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev);
-       struct tc35892 *tc35892 = tc35892_gpio->tc35892;
-       struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio;
-       int irq = platform_get_irq(pdev, 0);
-       int ret;
-
-       if (pdata->remove)
-               pdata->remove(tc35892, tc35892_gpio->chip.base);
-
-       ret = gpiochip_remove(&tc35892_gpio->chip);
-       if (ret < 0) {
-               dev_err(tc35892_gpio->dev,
-                       "unable to remove gpiochip: %d\n", ret);
-               return ret;
-       }
-
-       free_irq(irq, tc35892_gpio);
-       tc35892_gpio_irq_remove(tc35892_gpio);
-
-       platform_set_drvdata(pdev, NULL);
-       kfree(tc35892_gpio);
-
-       return 0;
-}
-
-static struct platform_driver tc35892_gpio_driver = {
-       .driver.name    = "tc35892-gpio",
-       .driver.owner   = THIS_MODULE,
-       .probe          = tc35892_gpio_probe,
-       .remove         = __devexit_p(tc35892_gpio_remove),
-};
-
-static int __init tc35892_gpio_init(void)
-{
-       return platform_driver_register(&tc35892_gpio_driver);
-}
-subsys_initcall(tc35892_gpio_init);
-
-static void __exit tc35892_gpio_exit(void)
-{
-       platform_driver_unregister(&tc35892_gpio_driver);
-}
-module_exit(tc35892_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TC35892 GPIO driver");
-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c
new file mode 100644 (file)
index 0000000..180d584
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tc3589x.h>
+
+/*
+ * These registers are modified under the irq bus lock and cached to avoid
+ * unnecessary writes in bus_sync_unlock.
+ */
+enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
+
+#define CACHE_NR_REGS  4
+#define CACHE_NR_BANKS 3
+
+struct tc3589x_gpio {
+       struct gpio_chip chip;
+       struct tc3589x *tc3589x;
+       struct device *dev;
+       struct mutex irq_lock;
+
+       int irq_base;
+
+       /* Caches of interrupt control registers for bus_lock */
+       u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
+       u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
+};
+
+static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip)
+{
+       return container_of(chip, struct tc3589x_gpio, chip);
+}
+
+static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+       u8 mask = 1 << (offset % 8);
+       int ret;
+
+       ret = tc3589x_reg_read(tc3589x, reg);
+       if (ret < 0)
+               return ret;
+
+       return ret & mask;
+}
+
+static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+       unsigned pos = offset % 8;
+       u8 data[] = {!!val << pos, 1 << pos};
+
+       tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
+}
+
+static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
+                                        unsigned offset, int val)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODIR0 + offset / 8;
+       unsigned pos = offset % 8;
+
+       tc3589x_gpio_set(chip, offset, val);
+
+       return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
+}
+
+static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
+                                       unsigned offset)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 reg = TC3589x_GPIODIR0 + offset / 8;
+       unsigned pos = offset % 8;
+
+       return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
+}
+
+static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+
+       return tc3589x_gpio->irq_base + offset;
+}
+
+static struct gpio_chip template_chip = {
+       .label                  = "tc3589x",
+       .owner                  = THIS_MODULE,
+       .direction_input        = tc3589x_gpio_direction_input,
+       .get                    = tc3589x_gpio_get,
+       .direction_output       = tc3589x_gpio_direction_output,
+       .set                    = tc3589x_gpio_set,
+       .to_irq                 = tc3589x_gpio_to_irq,
+       .can_sleep              = 1,
+};
+
+static int tc3589x_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+       struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+       int offset = irq - tc3589x_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       if (type == IRQ_TYPE_EDGE_BOTH) {
+               tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
+               return 0;
+       }
+
+       tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
+
+       if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
+               tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
+       else
+               tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
+
+       if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
+               tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
+       else
+               tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
+
+       return 0;
+}
+
+static void tc3589x_gpio_irq_lock(unsigned int irq)
+{
+       struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+
+       mutex_lock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_sync_unlock(unsigned int irq)
+{
+       struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       static const u8 regmap[] = {
+               [REG_IBE]       = TC3589x_GPIOIBE0,
+               [REG_IEV]       = TC3589x_GPIOIEV0,
+               [REG_IS]        = TC3589x_GPIOIS0,
+               [REG_IE]        = TC3589x_GPIOIE0,
+       };
+       int i, j;
+
+       for (i = 0; i < CACHE_NR_REGS; i++) {
+               for (j = 0; j < CACHE_NR_BANKS; j++) {
+                       u8 old = tc3589x_gpio->oldregs[i][j];
+                       u8 new = tc3589x_gpio->regs[i][j];
+
+                       if (new == old)
+                               continue;
+
+                       tc3589x_gpio->oldregs[i][j] = new;
+                       tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
+               }
+       }
+
+       mutex_unlock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_mask(unsigned int irq)
+{
+       struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+       int offset = irq - tc3589x_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
+}
+
+static void tc3589x_gpio_irq_unmask(unsigned int irq)
+{
+       struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+       int offset = irq - tc3589x_gpio->irq_base;
+       int regoffset = offset / 8;
+       int mask = 1 << (offset % 8);
+
+       tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
+}
+
+static struct irq_chip tc3589x_gpio_irq_chip = {
+       .name                   = "tc3589x-gpio",
+       .bus_lock               = tc3589x_gpio_irq_lock,
+       .bus_sync_unlock        = tc3589x_gpio_irq_sync_unlock,
+       .mask                   = tc3589x_gpio_irq_mask,
+       .unmask                 = tc3589x_gpio_irq_unmask,
+       .set_type               = tc3589x_gpio_irq_set_type,
+};
+
+static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
+{
+       struct tc3589x_gpio *tc3589x_gpio = dev;
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       u8 status[CACHE_NR_BANKS];
+       int ret;
+       int i;
+
+       ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
+                                ARRAY_SIZE(status), status);
+       if (ret < 0)
+               return IRQ_NONE;
+
+       for (i = 0; i < ARRAY_SIZE(status); i++) {
+               unsigned int stat = status[i];
+               if (!stat)
+                       continue;
+
+               while (stat) {
+                       int bit = __ffs(stat);
+                       int line = i * 8 + bit;
+
+                       handle_nested_irq(tc3589x_gpio->irq_base + line);
+                       stat &= ~(1 << bit);
+               }
+
+               tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
+{
+       int base = tc3589x_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+               set_irq_chip_data(irq, tc3589x_gpio);
+               set_irq_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
+                                        handle_simple_irq);
+               set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               set_irq_noprobe(irq);
+#endif
+       }
+
+       return 0;
+}
+
+static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
+{
+       int base = tc3589x_gpio->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, 0);
+#endif
+               set_irq_chip_and_handler(irq, NULL, NULL);
+               set_irq_chip_data(irq, NULL);
+       }
+}
+
+static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
+{
+       struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+       struct tc3589x_gpio_platform_data *pdata;
+       struct tc3589x_gpio *tc3589x_gpio;
+       int ret;
+       int irq;
+
+       pdata = tc3589x->pdata->gpio;
+       if (!pdata)
+               return -ENODEV;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
+       if (!tc3589x_gpio)
+               return -ENOMEM;
+
+       mutex_init(&tc3589x_gpio->irq_lock);
+
+       tc3589x_gpio->dev = &pdev->dev;
+       tc3589x_gpio->tc3589x = tc3589x;
+
+       tc3589x_gpio->chip = template_chip;
+       tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
+       tc3589x_gpio->chip.dev = &pdev->dev;
+       tc3589x_gpio->chip.base = pdata->gpio_base;
+
+       tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
+
+       /* Bring the GPIO module out of reset */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
+                              TC3589x_RSTCTRL_GPIRST, 0);
+       if (ret < 0)
+               goto out_free;
+
+       ret = tc3589x_gpio_irq_init(tc3589x_gpio);
+       if (ret)
+               goto out_free;
+
+       ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
+                                  "tc3589x-gpio", tc3589x_gpio);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+               goto out_removeirq;
+       }
+
+       ret = gpiochip_add(&tc3589x_gpio->chip);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
+               goto out_freeirq;
+       }
+
+       if (pdata->setup)
+               pdata->setup(tc3589x, tc3589x_gpio->chip.base);
+
+       platform_set_drvdata(pdev, tc3589x_gpio);
+
+       return 0;
+
+out_freeirq:
+       free_irq(irq, tc3589x_gpio);
+out_removeirq:
+       tc3589x_gpio_irq_remove(tc3589x_gpio);
+out_free:
+       kfree(tc3589x_gpio);
+       return ret;
+}
+
+static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
+{
+       struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
+       struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+       struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
+       int irq = platform_get_irq(pdev, 0);
+       int ret;
+
+       if (pdata->remove)
+               pdata->remove(tc3589x, tc3589x_gpio->chip.base);
+
+       ret = gpiochip_remove(&tc3589x_gpio->chip);
+       if (ret < 0) {
+               dev_err(tc3589x_gpio->dev,
+                       "unable to remove gpiochip: %d\n", ret);
+               return ret;
+       }
+
+       free_irq(irq, tc3589x_gpio);
+       tc3589x_gpio_irq_remove(tc3589x_gpio);
+
+       platform_set_drvdata(pdev, NULL);
+       kfree(tc3589x_gpio);
+
+       return 0;
+}
+
+static struct platform_driver tc3589x_gpio_driver = {
+       .driver.name    = "tc3589x-gpio",
+       .driver.owner   = THIS_MODULE,
+       .probe          = tc3589x_gpio_probe,
+       .remove         = __devexit_p(tc3589x_gpio_remove),
+};
+
+static int __init tc3589x_gpio_init(void)
+{
+       return platform_driver_register(&tc3589x_gpio_driver);
+}
+subsys_initcall(tc3589x_gpio_init);
+
+static void __exit tc3589x_gpio_exit(void)
+{
+       platform_driver_unregister(&tc3589x_gpio_driver);
+}
+module_exit(tc3589x_gpio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TC3589x GPIO driver");
+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
index 6985cb1da72cbc232919ab2bb93a52f26304a345..2baa6708e44cd835704ea832c861b7d5fe4b6e33 100644 (file)
@@ -156,12 +156,12 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
        { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
        { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
        { DRM_MODE_CONNECTOR_Component, "Component", 0 },
-       { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 },
-       { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
-       { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
-       { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
+       { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
+       { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
+       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
+       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
-       { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 },
+       { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
index 7ca59359fee2c83187f9cacc022d4af78bf67dd5..bede10a0340700b69717caf1da8e81ee0546ab00 100644 (file)
@@ -241,7 +241,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
        }
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               if (!drm_helper_encoder_in_use(encoder)) {
+               if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) {
                        drm_encoder_disable(encoder);
                        /* disconnector encoder from any connector */
                        encoder->crtc = NULL;
index 9d3a5030b6e1dfcfbf522a783d24f14816c7b813..16d5155edad14fd63dea3b10243a71c6bd3d0ea1 100644 (file)
@@ -585,10 +585,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        struct timeval now;
        unsigned long flags;
        unsigned int seq;
+       int ret;
 
        e = kzalloc(sizeof *e, GFP_KERNEL);
-       if (e == NULL)
-               return -ENOMEM;
+       if (e == NULL) {
+               ret = -ENOMEM;
+               goto err_put;
+       }
 
        e->pipe = pipe;
        e->base.pid = current->pid;
@@ -603,9 +606,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        spin_lock_irqsave(&dev->event_lock, flags);
 
        if (file_priv->event_space < sizeof e->event) {
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               kfree(e);
-               return -ENOMEM;
+               ret = -EBUSY;
+               goto err_unlock;
        }
 
        file_priv->event_space -= sizeof e->event;
@@ -626,7 +628,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        if ((seq - vblwait->request.sequence) <= (1 << 23)) {
                e->event.tv_sec = now.tv_sec;
                e->event.tv_usec = now.tv_usec;
-               drm_vblank_put(dev, e->pipe);
+               drm_vblank_put(dev, pipe);
                list_add_tail(&e->base.link, &e->base.file_priv->event_list);
                wake_up_interruptible(&e->base.file_priv->event_wait);
                trace_drm_vblank_event_delivered(current->pid, pipe,
@@ -638,6 +640,13 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        return 0;
+
+err_unlock:
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+       kfree(e);
+err_put:
+       drm_vblank_put(dev, pipe);
+       return ret;
 }
 
 /**
index 7a26f4dd21ae0a055036f78ce588ea4def08d73a..e6800819bca846f6a3fd102ef37e2632858247f8 100644 (file)
@@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_BLT:
                value = HAS_BLT(dev);
                break;
+       case I915_PARAM_HAS_COHERENT_RINGS:
+               value = 1;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
index 5e54821af99691ee139e3170eea00315cc15c750..275ec6ed43ae7dcc4f396322909296e00305c617 100644 (file)
@@ -4374,10 +4374,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
                 * use this buffer rather sooner than later, so issuing the required
                 * flush earlier is beneficial.
                 */
-               if (obj->write_domain & I915_GEM_GPU_DOMAINS)
+               if (obj->write_domain & I915_GEM_GPU_DOMAINS) {
                        i915_gem_flush_ring(dev, file_priv,
                                            obj_priv->ring,
                                            0, obj->write_domain);
+               } else if (obj_priv->ring->outstanding_lazy_request) {
+                       /* This ring is not being cleared by active usage,
+                        * so emit a request to do so.
+                        */
+                       u32 seqno = i915_add_request(dev,
+                                                    NULL, NULL,
+                                                    obj_priv->ring);
+                       if (seqno == 0)
+                               ret = -ENOMEM;
+               }
 
                /* Update the active list for the hardware's current position.
                 * Otherwise this only updates on a delayed timer or when irqs
index 25ed911a31127256b753970d2b2fca22d67f755d..878fc766a12cc05f6b30c90d53d65a52c6023727 100644 (file)
 #define  TRANS_DP_10BPC                (1<<9)
 #define  TRANS_DP_6BPC         (2<<9)
 #define  TRANS_DP_12BPC                (3<<9)
+#define  TRANS_DP_BPC_MASK     (3<<9)
 #define  TRANS_DP_VSYNC_ACTIVE_HIGH    (1<<4)
 #define  TRANS_DP_VSYNC_ACTIVE_LOW     0
 #define  TRANS_DP_HSYNC_ACTIVE_HIGH    (1<<3)
index 65c88f9ba12c825cad46592938f390e0eabf4ee6..2cb8e0b9f1ee4f9975fd3b8e863673d359bafdfe 100644 (file)
@@ -190,37 +190,6 @@ out:
        kfree(output.pointer);
 }
 
-static int intel_dsm_switchto(enum vga_switcheroo_client_id id)
-{
-       return 0;
-}
-
-static int intel_dsm_power_state(enum vga_switcheroo_client_id id,
-                                enum vga_switcheroo_state state)
-{
-       return 0;
-}
-
-static int intel_dsm_init(void)
-{
-       return 0;
-}
-
-static int intel_dsm_get_client_id(struct pci_dev *pdev)
-{
-       if (intel_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
-               return VGA_SWITCHEROO_IGD;
-       else
-               return VGA_SWITCHEROO_DIS;
-}
-
-static struct vga_switcheroo_handler intel_dsm_handler = {
-       .switchto = intel_dsm_switchto,
-       .power_state = intel_dsm_power_state,
-       .init = intel_dsm_init,
-       .get_client_id = intel_dsm_get_client_id,
-};
-
 static bool intel_dsm_pci_probe(struct pci_dev *pdev)
 {
        acpi_handle dhandle, intel_handle;
@@ -276,11 +245,8 @@ void intel_register_dsm_handler(void)
 {
        if (!intel_dsm_detect())
                return;
-
-       vga_switcheroo_register_handler(&intel_dsm_handler);
 }
 
 void intel_unregister_dsm_handler(void)
 {
-       vga_switcheroo_unregister_handler();
 }
index 255b52ee0091ace489d44e29bf3a6eb7c1e4d00c..d9b7092439ef59ab19acc9546a039ff60f0bb43c 100644 (file)
@@ -2120,9 +2120,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
                temp &= ~(TRANS_DP_PORT_SEL_MASK |
-                         TRANS_DP_SYNC_MASK);
+                         TRANS_DP_SYNC_MASK |
+                         TRANS_DP_BPC_MASK);
                temp |= (TRANS_DP_OUTPUT_ENABLE |
                         TRANS_DP_ENH_FRAMING);
+               temp |= TRANS_DP_8BPC;
 
                if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
                        temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
@@ -2712,27 +2714,19 @@ fdi_reduce_ratio(u32 *num, u32 *den)
        }
 }
 
-#define DATA_N 0x800000
-#define LINK_N 0x80000
-
 static void
 ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
                     int link_clock, struct fdi_m_n *m_n)
 {
-       u64 temp;
-
        m_n->tu = 64; /* default size */
 
-       temp = (u64) DATA_N * pixel_clock;
-       temp = div_u64(temp, link_clock);
-       m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes);
-       m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */
-       m_n->gmch_n = DATA_N;
+       /* BUG_ON(pixel_clock > INT_MAX / 36); */
+       m_n->gmch_m = bits_per_pixel * pixel_clock;
+       m_n->gmch_n = link_clock * nlanes * 8;
        fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
 
-       temp = (u64) LINK_N * pixel_clock;
-       m_n->link_m = div_u64(temp, link_clock);
-       m_n->link_n = LINK_N;
+       m_n->link_m = pixel_clock;
+       m_n->link_n = link_clock;
        fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
 }
 
@@ -3716,6 +3710,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        /* FDI link */
        if (HAS_PCH_SPLIT(dev)) {
+               int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
                int lane = 0, link_bw, bpp;
                /* CPU eDP doesn't require FDI link, so just set DP M/N
                   according to current link config */
@@ -3799,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
                intel_crtc->fdi_lanes = lane;
 
+               if (pixel_multiplier > 1)
+                       link_bw *= pixel_multiplier;
                ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
        }
 
@@ -5236,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
        .page_flip = intel_crtc_page_flip,
 };
 
+static void intel_sanitize_modesetting(struct drm_device *dev,
+                                      int pipe, int plane)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 reg, val;
+
+       if (HAS_PCH_SPLIT(dev))
+               return;
+
+       /* Who knows what state these registers were left in by the BIOS or
+        * grub?
+        *
+        * If we leave the registers in a conflicting state (e.g. with the
+        * display plane reading from the other pipe than the one we intend
+        * to use) then when we attempt to teardown the active mode, we will
+        * not disable the pipes and planes in the correct order -- leaving
+        * a plane reading from a disabled pipe and possibly leading to
+        * undefined behaviour.
+        */
+
+       reg = DSPCNTR(plane);
+       val = I915_READ(reg);
+
+       if ((val & DISPLAY_PLANE_ENABLE) == 0)
+               return;
+       if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
+               return;
+
+       /* This display plane is active and attached to the other CPU pipe. */
+       pipe = !pipe;
+
+       /* Disable the plane and wait for it to stop reading from the pipe. */
+       I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
+       intel_flush_display_plane(dev, plane);
+
+       if (IS_GEN2(dev))
+               intel_wait_for_vblank(dev, pipe);
+
+       if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+               return;
+
+       /* Switch off the pipe. */
+       reg = PIPECONF(pipe);
+       val = I915_READ(reg);
+       if (val & PIPECONF_ENABLE) {
+               I915_WRITE(reg, val & ~PIPECONF_ENABLE);
+               intel_wait_for_pipe_off(dev, pipe);
+       }
+}
 
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
@@ -5287,6 +5333,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
                    (unsigned long)intel_crtc);
+
+       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
index 300f64b4238bdcefa89ab02ee5ff862b6aeb0f78..df648cb4c29641cec581307b1c40a46d812fd58b 100644 (file)
@@ -1376,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t DP = intel_dp->DP;
 
+       if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
+               return;
+
        DRM_DEBUG_KMS("\n");
 
        if (is_edp(intel_dp)) {
@@ -1398,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        if (is_edp(intel_dp))
                DP |= DP_LINK_TRAIN_OFF;
+
+       if (!HAS_PCH_CPT(dev) &&
+           I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+               /* Hardware workaround: leaving our transcoder select
+                * set to transcoder B while it's off will prevent the
+                * corresponding HDMI output on transcoder A.
+                *
+                * Combine this with another hardware workaround:
+                * transcoder select bit can only be cleared while the
+                * port is enabled.
+                */
+               DP &= ~DP_PIPEB_SELECT;
+               I915_WRITE(intel_dp->output_reg, DP);
+
+               /* Changes to enable or select take place the vblank
+                * after being written.
+                */
+               intel_wait_for_vblank(intel_dp->base.base.dev,
+                                     intel_crtc->pipe);
+       }
+
        I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
        POSTING_READ(intel_dp->output_reg);
 }
index f79327fc66539937d686ba604823f81895f2fa83..25bcedf386fd5e07f93b2c2f77d78dd8dc905170 100644 (file)
@@ -68,7 +68,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
 /**
  * Sets the power state for the panel.
  */
-static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
+static void intel_lvds_enable(struct intel_lvds *intel_lvds)
 {
        struct drm_device *dev = intel_lvds->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -82,26 +82,61 @@ static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
                lvds_reg = LVDS;
        }
 
-       if (on) {
-               I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
-               I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
-               intel_panel_set_backlight(dev, dev_priv->backlight_level);
-       } else {
-               dev_priv->backlight_level = intel_panel_get_backlight(dev);
-
-               intel_panel_set_backlight(dev, 0);
-               I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
+       I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
 
-               if (intel_lvds->pfit_control) {
-                       if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
-                               DRM_ERROR("timed out waiting for panel to power off\n");
-                       I915_WRITE(PFIT_CONTROL, 0);
-                       intel_lvds->pfit_control = 0;
+       if (intel_lvds->pfit_dirty) {
+               /*
+                * Enable automatic panel scaling so that non-native modes
+                * fill the screen.  The panel fitter should only be
+                * adjusted whilst the pipe is disabled, according to
+                * register description and PRM.
+                */
+               DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
+                             intel_lvds->pfit_control,
+                             intel_lvds->pfit_pgm_ratios);
+               if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) {
+                       DRM_ERROR("timed out waiting for panel to power off\n");
+               } else {
+                       I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
+                       I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
                        intel_lvds->pfit_dirty = false;
                }
+       }
+
+       I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
+       POSTING_READ(lvds_reg);
+
+       intel_panel_set_backlight(dev, dev_priv->backlight_level);
+}
 
-               I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
+static void intel_lvds_disable(struct intel_lvds *intel_lvds)
+{
+       struct drm_device *dev = intel_lvds->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 ctl_reg, lvds_reg;
+
+       if (HAS_PCH_SPLIT(dev)) {
+               ctl_reg = PCH_PP_CONTROL;
+               lvds_reg = PCH_LVDS;
+       } else {
+               ctl_reg = PP_CONTROL;
+               lvds_reg = LVDS;
+       }
+
+       dev_priv->backlight_level = intel_panel_get_backlight(dev);
+       intel_panel_set_backlight(dev, 0);
+
+       I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
+
+       if (intel_lvds->pfit_control) {
+               if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
+                       DRM_ERROR("timed out waiting for panel to power off\n");
+
+               I915_WRITE(PFIT_CONTROL, 0);
+               intel_lvds->pfit_dirty = true;
        }
+
+       I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
        POSTING_READ(lvds_reg);
 }
 
@@ -110,9 +145,9 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
        struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
        if (mode == DRM_MODE_DPMS_ON)
-               intel_lvds_set_power(intel_lvds, true);
+               intel_lvds_enable(intel_lvds);
        else
-               intel_lvds_set_power(intel_lvds, false);
+               intel_lvds_disable(intel_lvds);
 
        /* XXX: We never power down the LVDS pairs. */
 }
@@ -411,43 +446,18 @@ static void intel_lvds_commit(struct drm_encoder *encoder)
        /* Always do a full power on as we do not know what state
         * we were left in.
         */
-       intel_lvds_set_power(intel_lvds, true);
+       intel_lvds_enable(intel_lvds);
 }
 
 static void intel_lvds_mode_set(struct drm_encoder *encoder,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode)
 {
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
        /*
         * The LVDS pin pair will already have been turned on in the
         * intel_crtc_mode_set since it has a large impact on the DPLL
         * settings.
         */
-
-       if (HAS_PCH_SPLIT(dev))
-               return;
-
-       if (!intel_lvds->pfit_dirty)
-               return;
-
-       /*
-        * Enable automatic panel scaling so that non-native modes fill the
-        * screen.  Should be enabled before the pipe is enabled, according to
-        * register description and PRM.
-        */
-       DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
-                     intel_lvds->pfit_control,
-                     intel_lvds->pfit_pgm_ratios);
-       if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
-               DRM_ERROR("timed out waiting for panel to power off\n");
-
-       I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
-       I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
-       intel_lvds->pfit_dirty = false;
 }
 
 /**
index b83306f9244b6c887d84976b4f1801449445941a..89a65be8a3f364359edaf6add71b6259affa3cbd 100644 (file)
@@ -156,23 +156,25 @@ static int init_ring_common(struct drm_device *dev,
 
        /* G45 ring initialization fails to reset head to zero */
        if (head != 0) {
-               DRM_ERROR("%s head not reset to zero "
-                               "ctl %08x head %08x tail %08x start %08x\n",
-                               ring->name,
-                               I915_READ_CTL(ring),
-                               I915_READ_HEAD(ring),
-                               I915_READ_TAIL(ring),
-                               I915_READ_START(ring));
+               DRM_DEBUG_KMS("%s head not reset to zero "
+                             "ctl %08x head %08x tail %08x start %08x\n",
+                             ring->name,
+                             I915_READ_CTL(ring),
+                             I915_READ_HEAD(ring),
+                             I915_READ_TAIL(ring),
+                             I915_READ_START(ring));
 
                I915_WRITE_HEAD(ring, 0);
 
-               DRM_ERROR("%s head forced to zero "
-                               "ctl %08x head %08x tail %08x start %08x\n",
-                               ring->name,
-                               I915_READ_CTL(ring),
-                               I915_READ_HEAD(ring),
-                               I915_READ_TAIL(ring),
-                               I915_READ_START(ring));
+               if (I915_READ_HEAD(ring) & HEAD_ADDR) {
+                       DRM_ERROR("failed to set %s head to zero "
+                                 "ctl %08x head %08x tail %08x start %08x\n",
+                                 ring->name,
+                                 I915_READ_CTL(ring),
+                                 I915_READ_HEAD(ring),
+                                 I915_READ_TAIL(ring),
+                                 I915_READ_START(ring));
+               }
        }
 
        I915_WRITE_CTL(ring,
index a3552594ccc44c69b398980e539daf348d62322a..4d7a2e1bdb90e498138eea542e22884c9e36eb0d 100644 (file)
@@ -878,12 +878,15 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
        u32 tmp;
 
        /* flush hdp cache so updates hit vram */
-       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+           !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
                u32 tmp;
 
                /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
                 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+                * This seems to cause problems on some AGP cards. Just use the old
+                * method for them.
                 */
                WREG32(HDP_DEBUG1, 0);
                tmp = readl((void __iomem *)ptr);
@@ -1195,8 +1198,10 @@ void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
                                mc->vram_end, mc->real_vram_size >> 20);
        } else {
                u64 base = 0;
-               if (rdev->flags & RADEON_IS_IGP)
-                       base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
+               if (rdev->flags & RADEON_IS_IGP) {
+                       base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
+                       base <<= 24;
+               }
                radeon_vram_location(rdev, &rdev->mc, base);
                rdev->mc.gtt_base_align = 0;
                radeon_gtt_location(rdev, mc);
@@ -3483,10 +3488,12 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
 void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
 {
        /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
-        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL.
+        * This seems to cause problems on some AGP cards. Just use the old
+        * method for them.
         */
        if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
-           rdev->vram_scratch.ptr) {
+           rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
                u32 tmp;
 
index d8ac1849180d5af379d5fe024057447c922d326f..e12e79326cb115a490ed5d94e0eda2a84ee400db 100644 (file)
@@ -286,7 +286,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
                mc->mc_vram_size = mc->aper_size;
        }
        mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-       dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
+       dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
                        mc->mc_vram_size >> 20, mc->vram_start,
                        mc->vram_end, mc->real_vram_size >> 20);
 }
@@ -323,7 +323,7 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
                mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align;
        }
        mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;
-       dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n",
+       dev_info(rdev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n",
                        mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end);
 }
 
index 1d067743fee068174e3a5e85eb0e2d47b5b712ee..a598d0049aa5938900a84c656c3cd9677010ee20 100644 (file)
@@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        u32 c = 0;
 
        rbo->placement.fpfn = 0;
-       rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT;
+       rbo->placement.lpfn = 0;
        rbo->placement.placement = rbo->placements;
        rbo->placement.busy_placement = rbo->placements;
        if (domain & RADEON_GEM_DOMAIN_VRAM)
@@ -91,7 +91,8 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
 {
        struct radeon_bo *bo;
        enum ttm_bo_type type;
-       int page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
+       unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
+       unsigned long max_size = 0;
        int r;
 
        if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
@@ -104,6 +105,14 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
        }
        *bo_ptr = NULL;
 
+       /* maximun bo size is the minimun btw visible vram and gtt size */
+       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+       if ((page_align << PAGE_SHIFT) >= max_size) {
+               printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
+                       __func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
+               return -ENOMEM;
+       }
+
 retry:
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
index 4bf969c0a32b5ee9cb667a4341759e651f58d569..be0fdd58aa29301fbe15f9186580d724ba769544 100644 (file)
@@ -916,27 +916,27 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        int nr = sensor_attr->index;
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1026_data *data = i2c_get_clientdata(client);
-       int val, orig_div, new_div, shift;
+       int val, orig_div, new_div;
 
        val = simple_strtol(buf, NULL, 10);
        new_div = DIV_TO_REG(val);
-       if (new_div == 0) {
-               return -EINVAL;
-       }
+
        mutex_lock(&data->update_lock);
        orig_div = data->fan_div[nr];
        data->fan_div[nr] = DIV_FROM_REG(new_div);
 
        if (nr < 4) { /* 0 <= nr < 4 */
-               shift = 2 * nr;
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[0]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[1]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[2]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[3]) << 6));
        } else { /* 3 < nr < 8 */
-               shift = 2 * (nr - 4);
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[4]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[5]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[6]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[7]) << 6));
        }
 
        if (data->fan_div[nr] != orig_div) {
index 14a5d981be7d07030a264352dbc8d8af1e158c2d..a428a92641954a640dd783f051fc9c5565c13d9b 100644 (file)
@@ -187,6 +187,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
+#define IT87_REG_PWM_DUTY(nr)  (0x63 + (nr) * 8)
 
 #define IT87_REG_VIN(nr)       (0x20 + (nr))
 #define IT87_REG_TEMP(nr)      (0x29 + (nr))
@@ -251,12 +252,16 @@ struct it87_data {
        u8 fan_main_ctrl;       /* Register value */
        u8 fan_ctl;             /* Register value */
 
-       /* The following 3 arrays correspond to the same registers. The
-        * meaning of bits 6-0 depends on the value of bit 7, and we want
-        * to preserve settings on mode changes, so we have to track all
-        * values separately. */
+       /* The following 3 arrays correspond to the same registers up to
+        * the IT8720F. The meaning of bits 6-0 depends on the value of bit
+        * 7, and we want to preserve settings on mode changes, so we have
+        * to track all values separately.
+        * Starting with the IT8721F, the manual PWM duty cycles are stored
+        * in separate registers (8-bit values), so the separate tracking
+        * is no longer needed, but it is still done to keep the driver
+        * simple. */
        u8 pwm_ctrl[3];         /* Register value */
-       u8 pwm_duty[3];         /* Manual PWM value set by user (bit 6-0) */
+       u8 pwm_duty[3];         /* Manual PWM value set by user */
        u8 pwm_temp_map[3];     /* PWM to temp. chan. mapping (bits 1-0) */
 
        /* Automatic fan speed control registers */
@@ -832,7 +837,9 @@ static ssize_t set_pwm_enable(struct device *dev,
                                 data->fan_main_ctrl);
        } else {
                if (val == 1)                           /* Manual mode */
-                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       data->pwm_ctrl[nr] = data->type == it8721 ?
+                                            data->pwm_temp_map[nr] :
+                                            data->pwm_duty[nr];
                else                                    /* Automatic mode */
                        data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
                it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
@@ -858,12 +865,25 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
-       data->pwm_duty[nr] = pwm_to_reg(data, val);
-       /* If we are in manual mode, write the duty cycle immediately;
-        * otherwise, just store it for later use. */
-       if (!(data->pwm_ctrl[nr] & 0x80)) {
-               data->pwm_ctrl[nr] = data->pwm_duty[nr];
-               it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+       if (data->type == it8721) {
+               /* If we are in automatic mode, the PWM duty cycle register
+                * is read-only so we can't write the value */
+               if (data->pwm_ctrl[nr] & 0x80) {
+                       mutex_unlock(&data->update_lock);
+                       return -EBUSY;
+               }
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               it87_write_value(data, IT87_REG_PWM_DUTY(nr),
+                                data->pwm_duty[nr]);
+       } else {
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               /* If we are in manual mode, write the duty cycle immediately;
+                * otherwise, just store it for later use. */
+               if (!(data->pwm_ctrl[nr] & 0x80)) {
+                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       it87_write_value(data, IT87_REG_PWM(nr),
+                                        data->pwm_ctrl[nr]);
+               }
        }
        mutex_unlock(&data->update_lock);
        return count;
@@ -1958,7 +1978,10 @@ static void __devinit it87_init_device(struct platform_device *pdev)
         *   channels to use when later setting to automatic mode later.
         *   Use a 1:1 mapping by default (we are clueless.)
         * In both cases, the value can (and should) be changed by the user
-        * prior to switching to a different mode. */
+        * prior to switching to a different mode.
+        * Note that this is no longer needed for the IT8721F and later, as
+        * these have separate registers for the temperature mapping and the
+        * manual duty cycle. */
        for (i = 0; i < 3; i++) {
                data->pwm_temp_map[i] = i;
                data->pwm_duty[i] = 0x7f;       /* Full speed */
@@ -2034,10 +2057,16 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
 {
        data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
-       if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+       if (data->type == it8721) {
                data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
-       else                            /* Manual mode */
-               data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+               data->pwm_duty[nr] = it87_read_value(data,
+                                                    IT87_REG_PWM_DUTY(nr));
+       } else {
+               if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+                       data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+               else                            /* Manual mode */
+                       data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+       }
 
        if (has_old_autopwm(data)) {
                int i;
index 00d975eb5b83dcc86ddd8d5f5b6846c9d370f6e6..c7e6d8e81656391e7f7919d5e4c92d08a69b1700 100644 (file)
@@ -205,7 +205,6 @@ LTC4215_ALARM(curr1_max_alarm,      (1 << 2),       LTC4215_STATUS);
 
 /* Power (virtual) */
 LTC4215_POWER(power1_input);
-LTC4215_ALARM(power1_alarm,    (1 << 3),       LTC4215_STATUS);
 
 /* Input Voltage */
 LTC4215_VOLTAGE(in1_input,                     LTC4215_ADIN);
@@ -214,6 +213,7 @@ LTC4215_ALARM(in1_min_alarm,        (1 << 1),       LTC4215_STATUS);
 
 /* Output Voltage */
 LTC4215_VOLTAGE(in2_input,                     LTC4215_SOURCE);
+LTC4215_ALARM(in2_min_alarm,   (1 << 3),       LTC4215_STATUS);
 
 /* Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
@@ -223,13 +223,13 @@ static struct attribute *ltc4215_attributes[] = {
        &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
 
        &sensor_dev_attr_power1_input.dev_attr.attr,
-       &sensor_dev_attr_power1_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in1_input.dev_attr.attr,
        &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
        &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
 
        NULL,
 };
index 80f70d3a744dc65024c868843a66cd336fd53ce5..c71492782bbd4dda6e1f4a585adbba419ce4694d 100644 (file)
@@ -999,7 +999,7 @@ static int __devinit intel_mid_i2c_probe(struct pci_dev *dev,
 
        /* Initialize struct members */
        snprintf(mrst->adap.name, sizeof(mrst->adap.name),
-               "MRST/Medfield I2C at %lx", start);
+               "Intel MID I2C at %lx", start);
        mrst->adap.owner = THIS_MODULE;
        mrst->adap.algo = &intel_mid_i2c_algorithm;
        mrst->adap.dev.parent = &dev->dev;
index 41665d2f9f93c1fa585533184468da72039fe7cf..c131d58bcb50d818e05ee0464581bceedfdbf20f 100644 (file)
@@ -273,8 +273,6 @@ static int intel_idle_probe(void)
 
        pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
 
-       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
-               lapic_timer_reliable_states = 0xFFFFFFFF;
 
        if (boot_cpu_data.x86 != 6)     /* family 6 */
                return -ENODEV;
@@ -286,8 +284,6 @@ static int intel_idle_probe(void)
        case 0x1F:      /* Core i7 and i5 Processor - Nehalem */
        case 0x2E:      /* Nehalem-EX Xeon */
        case 0x2F:      /* Westmere-EX Xeon */
-               lapic_timer_reliable_states = (1 << 1);  /* C1 */
-
        case 0x25:      /* Westmere */
        case 0x2C:      /* Westmere */
                cpuidle_state_table = nehalem_cstates;
@@ -295,7 +291,6 @@ static int intel_idle_probe(void)
 
        case 0x1C:      /* 28 - Atom Processor */
        case 0x26:      /* 38 - Lincroft Atom Processor */
-               lapic_timer_reliable_states = (1 << 1); /* C1 */
                cpuidle_state_table = atom_cstates;
                break;
 
@@ -303,10 +298,6 @@ static int intel_idle_probe(void)
        case 0x2D:      /* SNB Xeon */
                cpuidle_state_table = snb_cstates;
                break;
-#ifdef FUTURE_USE
-       case 0x17:      /* 23 - Core 2 Duo */
-               lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
-#endif
 
        default:
                pr_debug(PREFIX "does not run on family %d model %d\n",
@@ -314,6 +305,9 @@ static int intel_idle_probe(void)
                return -ENODEV;
        }
 
+       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
+               lapic_timer_reliable_states = 0xFFFFFFFF;
+
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
 
index b342248aec059060e19f64ffd69ec28af256682a..c42699285f8eb0d67745c359afadc6e125e7815d 100644 (file)
@@ -893,68 +893,81 @@ out:
        return ret ? ret : in_len;
 }
 
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+       struct ib_uverbs_wc tmp;
+
+       tmp.wr_id               = wc->wr_id;
+       tmp.status              = wc->status;
+       tmp.opcode              = wc->opcode;
+       tmp.vendor_err          = wc->vendor_err;
+       tmp.byte_len            = wc->byte_len;
+       tmp.ex.imm_data         = (__u32 __force) wc->ex.imm_data;
+       tmp.qp_num              = wc->qp->qp_num;
+       tmp.src_qp              = wc->src_qp;
+       tmp.wc_flags            = wc->wc_flags;
+       tmp.pkey_index          = wc->pkey_index;
+       tmp.slid                = wc->slid;
+       tmp.sl                  = wc->sl;
+       tmp.dlid_path_bits      = wc->dlid_path_bits;
+       tmp.port_num            = wc->port_num;
+       tmp.reserved            = 0;
+
+       if (copy_to_user(dest, &tmp, sizeof tmp))
+               return -EFAULT;
+
+       return 0;
+}
+
 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                          const char __user *buf, int in_len,
                          int out_len)
 {
        struct ib_uverbs_poll_cq       cmd;
-       struct ib_uverbs_poll_cq_resp *resp;
+       struct ib_uverbs_poll_cq_resp  resp;
+       u8 __user                     *header_ptr;
+       u8 __user                     *data_ptr;
        struct ib_cq                  *cq;
-       struct ib_wc                  *wc;
-       int                            ret = 0;
-       int                            i;
-       int                            rsize;
+       struct ib_wc                   wc;
+       int                            ret;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
-       if (!wc)
-               return -ENOMEM;
-
-       rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
-       resp = kmalloc(rsize, GFP_KERNEL);
-       if (!resp) {
-               ret = -ENOMEM;
-               goto out_wc;
-       }
-
        cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
-       if (!cq) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!cq)
+               return -EINVAL;
 
-       resp->count = ib_poll_cq(cq, cmd.ne, wc);
+       /* we copy a struct ib_uverbs_poll_cq_resp to user space */
+       header_ptr = (void __user *)(unsigned long) cmd.response;
+       data_ptr = header_ptr + sizeof resp;
 
-       put_cq_read(cq);
+       memset(&resp, 0, sizeof resp);
+       while (resp.count < cmd.ne) {
+               ret = ib_poll_cq(cq, 1, &wc);
+               if (ret < 0)
+                       goto out_put;
+               if (!ret)
+                       break;
+
+               ret = copy_wc_to_user(data_ptr, &wc);
+               if (ret)
+                       goto out_put;
 
-       for (i = 0; i < resp->count; i++) {
-               resp->wc[i].wr_id          = wc[i].wr_id;
-               resp->wc[i].status         = wc[i].status;
-               resp->wc[i].opcode         = wc[i].opcode;
-               resp->wc[i].vendor_err     = wc[i].vendor_err;
-               resp->wc[i].byte_len       = wc[i].byte_len;
-               resp->wc[i].ex.imm_data    = (__u32 __force) wc[i].ex.imm_data;
-               resp->wc[i].qp_num         = wc[i].qp->qp_num;
-               resp->wc[i].src_qp         = wc[i].src_qp;
-               resp->wc[i].wc_flags       = wc[i].wc_flags;
-               resp->wc[i].pkey_index     = wc[i].pkey_index;
-               resp->wc[i].slid           = wc[i].slid;
-               resp->wc[i].sl             = wc[i].sl;
-               resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
-               resp->wc[i].port_num       = wc[i].port_num;
+               data_ptr += sizeof(struct ib_uverbs_wc);
+               ++resp.count;
        }
 
-       if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+       if (copy_to_user(header_ptr, &resp, sizeof resp)) {
                ret = -EFAULT;
+               goto out_put;
+       }
 
-out:
-       kfree(resp);
+       ret = in_len;
 
-out_wc:
-       kfree(wc);
-       return ret ? ret : in_len;
+out_put:
+       put_cq_read(cq);
+       return ret;
 }
 
 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
index d53b9e900234e7ba95c2c0b9500a830b96c07803..27b6a3ce18caf2e996177e6c313fff2b21a4ad19 100644 (file)
@@ -245,6 +245,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
                goto err_free_tgfx;
         }
 
+       parport_put_port(pp);
        return tgfx;
 
  err_free_dev:
index b8c51b9781dbfb5e51c9a9d84071f534bf44e1d1..c76bd3183beb73aa115f6f28b9b8e53ed57bed01 100644 (file)
@@ -179,6 +179,22 @@ config KEYBOARD_GPIO
          To compile this driver as a module, choose M here: the
          module will be called gpio_keys.
 
+config KEYBOARD_GPIO_POLLED
+       tristate "Polled GPIO buttons"
+       depends on GENERIC_GPIO
+       select INPUT_POLLDEV
+       help
+         This driver implements support for buttons connected
+         to GPIO pins that are not capable of generating interrupts.
+
+         Say Y here if your device has buttons connected
+         directly to such GPIO pins.  Your board-specific
+         setup logic must also provide a platform device,
+         with configuration data saying which GPIOs are used.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gpio_keys_polled.
+
 config KEYBOARD_TCA6416
        tristate "TCA6416 Keypad Support"
        depends on I2C
@@ -443,6 +459,16 @@ config KEYBOARD_OMAP4
          To compile this driver as a module, choose M here: the
          module will be called omap4-keypad.
 
+config KEYBOARD_TC3589X
+       tristate "TC3589X Keypad support"
+       depends on MFD_TC3589X
+       help
+         Say Y here if you want to use the keypad controller on
+         TC35892/3 I/O expander.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tc3589x-keypad.
+
 config KEYBOARD_TNETV107X
        tristate "TI TNETV107X keypad support"
        depends on ARCH_DAVINCI_TNETV107X
index a34452e8ebe2a1cb190f82d5c5f9c037860fcf07..2aa6ce248b713ae279078371919e6073d0eef37d 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_BFIN)           += bf54x-keys.o
 obj-$(CONFIG_KEYBOARD_DAVINCI)         += davinci_keyscan.o
 obj-$(CONFIG_KEYBOARD_EP93XX)          += ep93xx_keypad.o
 obj-$(CONFIG_KEYBOARD_GPIO)            += gpio_keys.o
+obj-$(CONFIG_KEYBOARD_GPIO_POLLED)     += gpio_keys_polled.o
 obj-$(CONFIG_KEYBOARD_TCA6416)         += tca6416-keypad.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
@@ -40,6 +41,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC)               += sh_keysc.o
 obj-$(CONFIG_KEYBOARD_STMPE)           += stmpe-keypad.o
 obj-$(CONFIG_KEYBOARD_STOWAWAY)                += stowaway.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)          += sunkbd.o
+obj-$(CONFIG_KEYBOARD_TC3589X)         += tc3589x-keypad.o
 obj-$(CONFIG_KEYBOARD_TNETV107X)       += tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)         += twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)           += xtkbd.o
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
new file mode 100644 (file)
index 0000000..4c17aff
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ *  Driver for buttons on GPIO lines not capable of generating interrupts
+ *
+ *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
+ *
+ *  This file was based on: /drivers/input/misc/cobalt_btns.c
+ *     Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  also was based on: /drivers/input/keyboard/gpio_keys.c
+ *     Copyright 2005 Phil Blundell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#define DRV_NAME       "gpio-keys-polled"
+
+struct gpio_keys_button_data {
+       int last_state;
+       int count;
+       int threshold;
+       int can_sleep;
+};
+
+struct gpio_keys_polled_dev {
+       struct input_polled_dev *poll_dev;
+       struct device *dev;
+       struct gpio_keys_platform_data *pdata;
+       struct gpio_keys_button_data data[0];
+};
+
+static void gpio_keys_polled_check_state(struct input_dev *input,
+                                        struct gpio_keys_button *button,
+                                        struct gpio_keys_button_data *bdata)
+{
+       int state;
+
+       if (bdata->can_sleep)
+               state = !!gpio_get_value_cansleep(button->gpio);
+       else
+               state = !!gpio_get_value(button->gpio);
+
+       if (state != bdata->last_state) {
+               unsigned int type = button->type ?: EV_KEY;
+
+               input_event(input, type, button->code,
+                           !!(state ^ button->active_low));
+               input_sync(input);
+               bdata->count = 0;
+               bdata->last_state = state;
+       }
+}
+
+static void gpio_keys_polled_poll(struct input_polled_dev *dev)
+{
+       struct gpio_keys_polled_dev *bdev = dev->private;
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+       struct input_dev *input = dev->input;
+       int i;
+
+       for (i = 0; i < bdev->pdata->nbuttons; i++) {
+               struct gpio_keys_button_data *bdata = &bdev->data[i];
+
+               if (bdata->count < bdata->threshold)
+                       bdata->count++;
+               else
+                       gpio_keys_polled_check_state(input, &pdata->buttons[i],
+                                                    bdata);
+       }
+}
+
+static void gpio_keys_polled_open(struct input_polled_dev *dev)
+{
+       struct gpio_keys_polled_dev *bdev = dev->private;
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+
+       if (pdata->enable)
+               pdata->enable(bdev->dev);
+}
+
+static void gpio_keys_polled_close(struct input_polled_dev *dev)
+{
+       struct gpio_keys_polled_dev *bdev = dev->private;
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+
+       if (pdata->disable)
+               pdata->disable(bdev->dev);
+}
+
+static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+{
+       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       struct gpio_keys_polled_dev *bdev;
+       struct input_polled_dev *poll_dev;
+       struct input_dev *input;
+       int error;
+       int i;
+
+       if (!pdata || !pdata->poll_interval)
+               return -EINVAL;
+
+       bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
+                      pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+                      GFP_KERNEL);
+       if (!bdev) {
+               dev_err(dev, "no memory for private data\n");
+               return -ENOMEM;
+       }
+
+       poll_dev = input_allocate_polled_device();
+       if (!poll_dev) {
+               dev_err(dev, "no memory for polled device\n");
+               error = -ENOMEM;
+               goto err_free_bdev;
+       }
+
+       poll_dev->private = bdev;
+       poll_dev->poll = gpio_keys_polled_poll;
+       poll_dev->poll_interval = pdata->poll_interval;
+       poll_dev->open = gpio_keys_polled_open;
+       poll_dev->close = gpio_keys_polled_close;
+
+       input = poll_dev->input;
+
+       input->evbit[0] = BIT(EV_KEY);
+       input->name = pdev->name;
+       input->phys = DRV_NAME"/input0";
+       input->dev.parent = &pdev->dev;
+
+       input->id.bustype = BUS_HOST;
+       input->id.vendor = 0x0001;
+       input->id.product = 0x0001;
+       input->id.version = 0x0100;
+
+       for (i = 0; i < pdata->nbuttons; i++) {
+               struct gpio_keys_button *button = &pdata->buttons[i];
+               struct gpio_keys_button_data *bdata = &bdev->data[i];
+               unsigned int gpio = button->gpio;
+               unsigned int type = button->type ?: EV_KEY;
+
+               if (button->wakeup) {
+                       dev_err(dev, DRV_NAME " does not support wakeup\n");
+                       error = -EINVAL;
+                       goto err_free_gpio;
+               }
+
+               error = gpio_request(gpio,
+                                    button->desc ? button->desc : DRV_NAME);
+               if (error) {
+                       dev_err(dev, "unable to claim gpio %u, err=%d\n",
+                               gpio, error);
+                       goto err_free_gpio;
+               }
+
+               error = gpio_direction_input(gpio);
+               if (error) {
+                       dev_err(dev,
+                               "unable to set direction on gpio %u, err=%d\n",
+                               gpio, error);
+                       goto err_free_gpio;
+               }
+
+               bdata->can_sleep = gpio_cansleep(gpio);
+               bdata->last_state = -1;
+               bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
+                                               pdata->poll_interval);
+
+               input_set_capability(input, type, button->code);
+       }
+
+       bdev->poll_dev = poll_dev;
+       bdev->dev = dev;
+       bdev->pdata = pdata;
+       platform_set_drvdata(pdev, bdev);
+
+       error = input_register_polled_device(poll_dev);
+       if (error) {
+               dev_err(dev, "unable to register polled device, err=%d\n",
+                       error);
+               goto err_free_gpio;
+       }
+
+       /* report initial state of the buttons */
+       for (i = 0; i < pdata->nbuttons; i++)
+               gpio_keys_polled_check_state(input, &pdata->buttons[i],
+                                        &bdev->data[i]);
+
+       return 0;
+
+err_free_gpio:
+       while (--i >= 0)
+               gpio_free(pdata->buttons[i].gpio);
+
+       input_free_polled_device(poll_dev);
+
+err_free_bdev:
+       kfree(bdev);
+
+       platform_set_drvdata(pdev, NULL);
+       return error;
+}
+
+static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+{
+       struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+       struct gpio_keys_platform_data *pdata = bdev->pdata;
+       int i;
+
+       input_unregister_polled_device(bdev->poll_dev);
+
+       for (i = 0; i < pdata->nbuttons; i++)
+               gpio_free(pdata->buttons[i].gpio);
+
+       input_free_polled_device(bdev->poll_dev);
+
+       kfree(bdev);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver gpio_keys_polled_driver = {
+       .probe  = gpio_keys_polled_probe,
+       .remove = __devexit_p(gpio_keys_polled_remove),
+       .driver = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init gpio_keys_polled_init(void)
+{
+       return platform_driver_register(&gpio_keys_polled_driver);
+}
+
+static void __exit gpio_keys_polled_exit(void)
+{
+       platform_driver_unregister(&gpio_keys_polled_driver);
+}
+
+module_init(gpio_keys_polled_init);
+module_exit(gpio_keys_polled_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_DESCRIPTION("Polled GPIO Buttons driver");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
new file mode 100644 (file)
index 0000000..69dc0cb
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * License Terms: GNU General Public License, version 2
+ *
+ * TC35893 MFD Keypad Controller driver
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/mfd/tc3589x.h>
+
+/* Maximum supported keypad matrix row/columns size */
+#define TC3589x_MAX_KPROW               8
+#define TC3589x_MAX_KPCOL               12
+
+/* keypad related Constants */
+#define TC3589x_MAX_DEBOUNCE_SETTLE     0xFF
+#define DEDICATED_KEY_VAL              0xFF
+
+/* Pull up/down masks */
+#define TC3589x_NO_PULL_MASK           0x0
+#define TC3589x_PULL_DOWN_MASK         0x1
+#define TC3589x_PULL_UP_MASK           0x2
+#define TC3589x_PULLUP_ALL_MASK                0xAA
+#define TC3589x_IO_PULL_VAL(index, mask)       ((mask)<<((index)%4)*2))
+
+/* Bit masks for IOCFG register */
+#define IOCFG_BALLCFG          0x01
+#define IOCFG_IG               0x08
+
+#define KP_EVCODE_COL_MASK     0x0F
+#define KP_EVCODE_ROW_MASK     0x70
+#define KP_RELEASE_EVT_MASK    0x80
+
+#define KP_ROW_SHIFT           4
+
+#define KP_NO_VALID_KEY_MASK   0x7F
+
+/* bit masks for RESTCTRL register */
+#define TC3589x_KBDRST         0x2
+#define TC3589x_IRQRST         0x10
+#define TC3589x_RESET_ALL      0x1B
+
+/* KBDMFS register bit mask */
+#define TC3589x_KBDMFS_EN      0x1
+
+/* CLKEN register bitmask */
+#define KPD_CLK_EN             0x1
+
+/* RSTINTCLR register bit mask */
+#define IRQ_CLEAR              0x1
+
+/* bit masks for keyboard interrupts*/
+#define TC3589x_EVT_LOSS_INT   0x8
+#define TC3589x_EVT_INT                0x4
+#define TC3589x_KBD_LOSS_INT   0x2
+#define TC3589x_KBD_INT                0x1
+
+/* bit masks for keyboard interrupt clear*/
+#define TC3589x_EVT_INT_CLR    0x2
+#define TC3589x_KBD_INT_CLR    0x1
+
+#define TC3589x_KBD_KEYMAP_SIZE     64
+
+/**
+ * struct tc_keypad - data structure used by keypad driver
+ * @input:      pointer to input device object
+ * @board:      keypad platform device
+ * @krow:      number of rows
+ * @kcol:      number of coloumns
+ * @keymap:     matrix scan code table for keycodes
+ */
+struct tc_keypad {
+       struct tc3589x *tc3589x;
+       struct input_dev *input;
+       const struct tc3589x_keypad_platform_data *board;
+       unsigned int krow;
+       unsigned int kcol;
+       unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE];
+       bool keypad_stopped;
+};
+
+static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad)
+{
+       int ret;
+       struct tc3589x *tc3589x = keypad->tc3589x;
+       u8 settle_time = keypad->board->settle_time;
+       u8 dbounce_period = keypad->board->debounce_period;
+       u8 rows = keypad->board->krow & 0xf;    /* mask out the nibble */
+       u8 column = keypad->board->kcol & 0xf;  /* mask out the nibble */
+
+       /* validate platform configurations */
+       if (keypad->board->kcol > TC3589x_MAX_KPCOL ||
+           keypad->board->krow > TC3589x_MAX_KPROW ||
+           keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE ||
+           keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE)
+               return -EINVAL;
+
+       /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */
+       ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE,
+                       (rows << KP_ROW_SHIFT) | column);
+       if (ret < 0)
+               return ret;
+
+       /* configure dedicated key config, no dedicated key selected */
+       ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL);
+       if (ret < 0)
+               return ret;
+
+       ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL);
+       if (ret < 0)
+               return ret;
+
+       /* Configure settle time */
+       ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time);
+       if (ret < 0)
+               return ret;
+
+       /* Configure debounce time */
+       ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period);
+       if (ret < 0)
+               return ret;
+
+       /* Start of initialise keypad GPIOs */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG);
+       if (ret < 0)
+               return ret;
+
+       /* Configure pull-up resistors for all row GPIOs */
+       ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB,
+                                       TC3589x_PULLUP_ALL_MASK);
+       if (ret < 0)
+               return ret;
+
+       ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB,
+                                       TC3589x_PULLUP_ALL_MASK);
+       if (ret < 0)
+               return ret;
+
+       /* Configure pull-up resistors for all column GPIOs */
+       ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB,
+                       TC3589x_PULLUP_ALL_MASK);
+       if (ret < 0)
+               return ret;
+
+       ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB,
+                       TC3589x_PULLUP_ALL_MASK);
+       if (ret < 0)
+               return ret;
+
+       ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB,
+                       TC3589x_PULLUP_ALL_MASK);
+
+       return ret;
+}
+
+#define TC35893_DATA_REGS              4
+#define TC35893_KEYCODE_FIFO_EMPTY     0x7f
+#define TC35893_KEYCODE_FIFO_CLEAR     0xff
+#define TC35893_KEYPAD_ROW_SHIFT       0x3
+
+static irqreturn_t tc3589x_keypad_irq(int irq, void *dev)
+{
+       struct tc_keypad *keypad = dev;
+       struct tc3589x *tc3589x = keypad->tc3589x;
+       u8 i, row_index, col_index, kbd_code, up;
+       u8 code;
+
+       for (i = 0; i < TC35893_DATA_REGS * 2; i++) {
+               kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO);
+
+               /* loop till fifo is empty and no more keys are pressed */
+               if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY ||
+                               kbd_code == TC35893_KEYCODE_FIFO_CLEAR)
+                       continue;
+
+               /* valid key is found */
+               col_index = kbd_code & KP_EVCODE_COL_MASK;
+               row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT;
+               code = MATRIX_SCAN_CODE(row_index, col_index,
+                                               TC35893_KEYPAD_ROW_SHIFT);
+               up = kbd_code & KP_RELEASE_EVT_MASK;
+
+               input_event(keypad->input, EV_MSC, MSC_SCAN, code);
+               input_report_key(keypad->input, keypad->keymap[code], !up);
+               input_sync(keypad->input);
+       }
+
+       /* clear IRQ */
+       tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
+                       0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
+       /* enable IRQ */
+       tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
+                       0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
+
+       return IRQ_HANDLED;
+}
+
+static int tc3589x_keypad_enable(struct tc_keypad *keypad)
+{
+       struct tc3589x *tc3589x = keypad->tc3589x;
+       int ret;
+
+       /* pull the keypad module out of reset */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0);
+       if (ret < 0)
+               return ret;
+
+       /* configure KBDMFS */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN);
+       if (ret < 0)
+               return ret;
+
+       /* enable the keypad clock */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN);
+       if (ret < 0)
+               return ret;
+
+       /* clear pending IRQs */
+       ret =  tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1);
+       if (ret < 0)
+               return ret;
+
+       /* enable the IRQs */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0,
+                                       TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT);
+       if (ret < 0)
+               return ret;
+
+       keypad->keypad_stopped = false;
+
+       return ret;
+}
+
+static int tc3589x_keypad_disable(struct tc_keypad *keypad)
+{
+       struct tc3589x *tc3589x = keypad->tc3589x;
+       int ret;
+
+       /* clear IRQ */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC,
+                       0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR);
+       if (ret < 0)
+               return ret;
+
+       /* disable all interrupts */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK,
+                       ~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0);
+       if (ret < 0)
+               return ret;
+
+       /* disable the keypad module */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0);
+       if (ret < 0)
+               return ret;
+
+       /* put the keypad module into reset */
+       ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1);
+
+       keypad->keypad_stopped = true;
+
+       return ret;
+}
+
+static int tc3589x_keypad_open(struct input_dev *input)
+{
+       int error;
+       struct tc_keypad *keypad = input_get_drvdata(input);
+
+       /* enable the keypad module */
+       error = tc3589x_keypad_enable(keypad);
+       if (error < 0) {
+               dev_err(&input->dev, "failed to enable keypad module\n");
+               return error;
+       }
+
+       error = tc3589x_keypad_init_key_hardware(keypad);
+       if (error < 0) {
+               dev_err(&input->dev, "failed to configure keypad module\n");
+               return error;
+       }
+
+       return 0;
+}
+
+static void tc3589x_keypad_close(struct input_dev *input)
+{
+       struct tc_keypad *keypad = input_get_drvdata(input);
+
+       /* disable the keypad module */
+       tc3589x_keypad_disable(keypad);
+}
+
+static int __devinit tc3589x_keypad_probe(struct platform_device *pdev)
+{
+       struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+       struct tc_keypad *keypad;
+       struct input_dev *input;
+       const struct tc3589x_keypad_platform_data *plat;
+       int error, irq;
+
+       plat = tc3589x->pdata->keypad;
+       if (!plat) {
+               dev_err(&pdev->dev, "invalid keypad platform data\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!keypad || !input) {
+               dev_err(&pdev->dev, "failed to allocate keypad memory\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       keypad->board = plat;
+       keypad->input = input;
+       keypad->tc3589x = tc3589x;
+
+       input->id.bustype = BUS_I2C;
+       input->name = pdev->name;
+       input->dev.parent = &pdev->dev;
+
+       input->keycode = keypad->keymap;
+       input->keycodesize = sizeof(keypad->keymap[0]);
+       input->keycodemax = ARRAY_SIZE(keypad->keymap);
+
+       input->open = tc3589x_keypad_open;
+       input->close = tc3589x_keypad_close;
+
+       input_set_drvdata(input, keypad);
+
+       input_set_capability(input, EV_MSC, MSC_SCAN);
+
+       __set_bit(EV_KEY, input->evbit);
+       if (!plat->no_autorepeat)
+               __set_bit(EV_REP, input->evbit);
+
+       matrix_keypad_build_keymap(plat->keymap_data, 0x3,
+                       input->keycode, input->keybit);
+
+       error = request_threaded_irq(irq, NULL,
+                       tc3589x_keypad_irq, plat->irqtype,
+                       "tc3589x-keypad", keypad);
+       if (error < 0) {
+               dev_err(&pdev->dev,
+                               "Could not allocate irq %d,error %d\n",
+                               irq, error);
+               goto err_free_mem;
+       }
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(&pdev->dev, "Could not register input device\n");
+               goto err_free_irq;
+       }
+
+       /* let platform decide if keypad is a wakeup source or not */
+       device_init_wakeup(&pdev->dev, plat->enable_wakeup);
+       device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup);
+
+       platform_set_drvdata(pdev, keypad);
+
+       return 0;
+
+err_free_irq:
+       free_irq(irq, keypad);
+err_free_mem:
+       input_free_device(input);
+       kfree(keypad);
+       return error;
+}
+
+static int __devexit tc3589x_keypad_remove(struct platform_device *pdev)
+{
+       struct tc_keypad *keypad = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (!keypad->keypad_stopped)
+               tc3589x_keypad_disable(keypad);
+
+       free_irq(irq, keypad);
+
+       input_unregister_device(keypad->input);
+
+       kfree(keypad);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int tc3589x_keypad_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct tc_keypad *keypad = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       /* keypad is already off; we do nothing */
+       if (keypad->keypad_stopped)
+               return 0;
+
+       /* if device is not a wakeup source, disable it for powersave */
+       if (!device_may_wakeup(&pdev->dev))
+               tc3589x_keypad_disable(keypad);
+       else
+               enable_irq_wake(irq);
+
+       return 0;
+}
+
+static int tc3589x_keypad_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct tc_keypad *keypad = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (!keypad->keypad_stopped)
+               return 0;
+
+       /* enable the device to resume normal operations */
+       if (!device_may_wakeup(&pdev->dev))
+               tc3589x_keypad_enable(keypad);
+       else
+               disable_irq_wake(irq);
+
+       return 0;
+}
+
+static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
+                              tc3589x_keypad_suspend, tc3589x_keypad_resume);
+#endif
+
+static struct platform_driver tc3589x_keypad_driver = {
+       .driver.name  = "tc3589x-keypad",
+       .driver.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+       .driver.pm = &tc3589x_keypad_dev_pm_ops,
+#endif
+       .probe = tc3589x_keypad_probe,
+       .remove = __devexit_p(tc3589x_keypad_remove),
+};
+
+static int __init tc3589x_keypad_init(void)
+{
+       return platform_driver_register(&tc3589x_keypad_driver);
+}
+module_init(tc3589x_keypad_init);
+
+static void __exit tc3589x_keypad_exit(void)
+{
+       return platform_driver_unregister(&tc3589x_keypad_driver);
+}
+module_exit(tc3589x_keypad_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer");
+MODULE_DESCRIPTION("TC35893 Keypad Driver");
+MODULE_ALIAS("platform:tc3589x-keypad")
index 613a3652f98f5f787fa619807f10de67aa8634c5..0aefaa8858714ba6e9963a9e6cd1f0c13fbab963 100644 (file)
@@ -51,7 +51,8 @@
 #define SYN_EXT_CAP_REQUESTS(c)                (((c) & 0x700000) >> 20)
 #define SYN_CAP_MULTI_BUTTON_NO(ec)    (((ec) & 0x00f000) >> 12)
 #define SYN_CAP_PRODUCT_ID(ec)         (((ec) & 0xff0000) >> 16)
-#define SYN_CAP_CLICKPAD(ex0c)         ((ex0c) & 0x100100)
+#define SYN_CAP_CLICKPAD(ex0c)         ((ex0c) & 0x100000) /* 1-button ClickPad */
+#define SYN_CAP_CLICKPAD2BTN(ex0c)     ((ex0c) & 0x000100) /* 2-button ClickPad */
 #define SYN_CAP_MAX_DIMENSIONS(ex0c)   ((ex0c) & 0x020000)
 
 /* synaptics modes query bits */
index b3252ef1e2797e6b7f640322bb8cbf4a6ecc61bd..4852b440960abadea47ab158dc8e6e6140970b06 100644 (file)
@@ -1436,6 +1436,12 @@ static struct wacom_features wacom_features_0xD2 =
        { "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD3 =
        { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD8 =
+       { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xDA =
+       { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xDB =
+       { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13530, 1023, 63, BAMBOO_PT };
 
 #define USB_DEVICE_WACOM(prod)                                 \
        USB_DEVICE(USB_VENDOR_ID_WACOM, prod),                  \
@@ -1504,6 +1510,9 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
        { USB_DEVICE_WACOM(0xD3) },
+       { USB_DEVICE_WACOM(0xD8) },
+       { USB_DEVICE_WACOM(0xDA) },
+       { USB_DEVICE_WACOM(0xDB) },
        { USB_DEVICE_WACOM(0xF0) },
        { USB_DEVICE_WACOM(0xCC) },
        { USB_DEVICE_WACOM(0x90) },
index f45f80f6d3369b03f8b6e1e6a8bcebc827cf3377..73fd6642b681b92a074b6e8ab2619b65768292f7 100644 (file)
@@ -178,6 +178,7 @@ static const struct usb_device_id usbtouch_devices[] = {
 
 #ifdef CONFIG_TOUCHSCREEN_USB_ITM
        {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
+       {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM},
 #endif
 
 #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
index 84c46a161927999ebfc6c5d56d98e76247e66ae4..e71c5fa527f59ec3e6ea5fd6ce7d09746bfc437e 100644 (file)
@@ -371,10 +371,15 @@ static void md_end_flush(struct bio *bio, int err)
        bio_put(bio);
 }
 
-static void submit_flushes(mddev_t *mddev)
+static void md_submit_flush_data(struct work_struct *ws);
+
+static void submit_flushes(struct work_struct *ws)
 {
+       mddev_t *mddev = container_of(ws, mddev_t, flush_work);
        mdk_rdev_t *rdev;
 
+       INIT_WORK(&mddev->flush_work, md_submit_flush_data);
+       atomic_set(&mddev->flush_pending, 1);
        rcu_read_lock();
        list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
                if (rdev->raid_disk >= 0 &&
@@ -397,6 +402,8 @@ static void submit_flushes(mddev_t *mddev)
                        rdev_dec_pending(rdev, mddev);
                }
        rcu_read_unlock();
+       if (atomic_dec_and_test(&mddev->flush_pending))
+               queue_work(md_wq, &mddev->flush_work);
 }
 
 static void md_submit_flush_data(struct work_struct *ws)
@@ -404,8 +411,6 @@ static void md_submit_flush_data(struct work_struct *ws)
        mddev_t *mddev = container_of(ws, mddev_t, flush_work);
        struct bio *bio = mddev->flush_bio;
 
-       atomic_set(&mddev->flush_pending, 1);
-
        if (bio->bi_size == 0)
                /* an empty barrier - all done */
                bio_endio(bio, 0);
@@ -414,10 +419,9 @@ static void md_submit_flush_data(struct work_struct *ws)
                if (mddev->pers->make_request(mddev, bio))
                        generic_make_request(bio);
        }
-       if (atomic_dec_and_test(&mddev->flush_pending)) {
-               mddev->flush_bio = NULL;
-               wake_up(&mddev->sb_wait);
-       }
+
+       mddev->flush_bio = NULL;
+       wake_up(&mddev->sb_wait);
 }
 
 void md_flush_request(mddev_t *mddev, struct bio *bio)
@@ -429,13 +433,8 @@ void md_flush_request(mddev_t *mddev, struct bio *bio)
        mddev->flush_bio = bio;
        spin_unlock_irq(&mddev->write_lock);
 
-       atomic_set(&mddev->flush_pending, 1);
-       INIT_WORK(&mddev->flush_work, md_submit_flush_data);
-
-       submit_flushes(mddev);
-
-       if (atomic_dec_and_test(&mddev->flush_pending))
-               queue_work(md_wq, &mddev->flush_work);
+       INIT_WORK(&mddev->flush_work, submit_flushes);
+       queue_work(md_wq, &mddev->flush_work);
 }
 EXPORT_SYMBOL(md_flush_request);
 
@@ -5160,7 +5159,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                                PTR_ERR(rdev));
                        return PTR_ERR(rdev);
                }
-               /* set save_raid_disk if appropriate */
+               /* set saved_raid_disk if appropriate */
                if (!mddev->persistent) {
                        if (info->state & (1<<MD_DISK_SYNC)  &&
                            info->raid_disk < mddev->raid_disks)
@@ -5170,7 +5169,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                } else
                        super_types[mddev->major_version].
                                validate_super(mddev, rdev);
-               rdev->saved_raid_disk = rdev->raid_disk;
+               if (test_bit(In_sync, &rdev->flags))
+                       rdev->saved_raid_disk = rdev->raid_disk;
+               else
+                       rdev->saved_raid_disk = -1;
 
                clear_bit(In_sync, &rdev->flags); /* just to be sure */
                if (info->state & (1<<MD_DISK_WRITEMOSTLY))
@@ -6042,9 +6044,8 @@ static int md_thread(void * arg)
                         || kthread_should_stop(),
                         thread->timeout);
 
-               clear_bit(THREAD_WAKEUP, &thread->flags);
-
-               thread->run(thread->mddev);
+               if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags))
+                       thread->run(thread->mddev);
        }
 
        return 0;
index c67aa54694ae72605b2165949fe1033dc2d542b9..0641674827f06786dee5549ada83b23820928748 100644 (file)
@@ -2397,13 +2397,13 @@ static int run(mddev_t *mddev)
        return 0;
 
 out_free_conf:
+       md_unregister_thread(mddev->thread);
        if (conf->r10bio_pool)
                mempool_destroy(conf->r10bio_pool);
        safe_put_page(conf->tmppage);
        kfree(conf->mirrors);
        kfree(conf);
        mddev->private = NULL;
-       md_unregister_thread(mddev->thread);
 out:
        return -EIO;
 }
index 3a1493b8b5e565c1f5f263494efc1bc6a1405034..e8e704f52746d319b02c8d755cfa58d6c69a0308 100644 (file)
@@ -218,12 +218,12 @@ config MFD_STMPE
                Keypad: stmpe-keypad
                Touchscreen: stmpe-ts
 
-config MFD_TC35892
-       bool "Support Toshiba TC35892"
+config MFD_TC3589X
+       bool "Support Toshiba TC35892 and variants"
        depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
        help
-         Support for the Toshiba TC35892 I/O Expander.
+         Support for the Toshiba TC35892 and variants I/O Expander.
 
          This driver provides common support for accessing the device,
          additional drivers must be enabled in order to use the
index f54b3659abbb70bba716693396467bba5b4b035e..e590d1e44cf04110bcab9d0ed82882fe90a9a971 100644 (file)
@@ -16,7 +16,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)  += davinci_voicecodec.o
 obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
 
 obj-$(CONFIG_MFD_STMPE)                += stmpe.o
-obj-$(CONFIG_MFD_TC35892)      += tc35892.o
+obj-$(CONFIG_MFD_TC3589X)      += tc3589x.o
 obj-$(CONFIG_MFD_T7L66XB)      += t7l66xb.o tmio_core.o
 obj-$(CONFIG_MFD_TC6387XB)     += tc6387xb.o tmio_core.o
 obj-$(CONFIG_MFD_TC6393XB)     += tc6393xb.o tmio_core.o
diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c
deleted file mode 100644 (file)
index e619e2a..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/tc35892.h>
-
-/**
- * tc35892_reg_read() - read a single TC35892 register
- * @tc35892:   Device to read from
- * @reg:       Register to read
- */
-int tc35892_reg_read(struct tc35892 *tc35892, u8 reg)
-{
-       int ret;
-
-       ret = i2c_smbus_read_byte_data(tc35892->i2c, reg);
-       if (ret < 0)
-               dev_err(tc35892->dev, "failed to read reg %#x: %d\n",
-                       reg, ret);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_reg_read);
-
-/**
- * tc35892_reg_read() - write a single TC35892 register
- * @tc35892:   Device to write to
- * @reg:       Register to read
- * @data:      Value to write
- */
-int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data)
-{
-       int ret;
-
-       ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data);
-       if (ret < 0)
-               dev_err(tc35892->dev, "failed to write reg %#x: %d\n",
-                       reg, ret);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_reg_write);
-
-/**
- * tc35892_block_read() - read multiple TC35892 registers
- * @tc35892:   Device to read from
- * @reg:       First register
- * @length:    Number of registers
- * @values:    Buffer to write to
- */
-int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values)
-{
-       int ret;
-
-       ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values);
-       if (ret < 0)
-               dev_err(tc35892->dev, "failed to read regs %#x: %d\n",
-                       reg, ret);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_block_read);
-
-/**
- * tc35892_block_write() - write multiple TC35892 registers
- * @tc35892:   Device to write to
- * @reg:       First register
- * @length:    Number of registers
- * @values:    Values to write
- */
-int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
-                       const u8 *values)
-{
-       int ret;
-
-       ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length,
-                                            values);
-       if (ret < 0)
-               dev_err(tc35892->dev, "failed to write regs %#x: %d\n",
-                       reg, ret);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_block_write);
-
-/**
- * tc35892_set_bits() - set the value of a bitfield in a TC35892 register
- * @tc35892:   Device to write to
- * @reg:       Register to write
- * @mask:      Mask of bits to set
- * @values:    Value to set
- */
-int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val)
-{
-       int ret;
-
-       mutex_lock(&tc35892->lock);
-
-       ret = tc35892_reg_read(tc35892, reg);
-       if (ret < 0)
-               goto out;
-
-       ret &= ~mask;
-       ret |= val;
-
-       ret = tc35892_reg_write(tc35892, reg, ret);
-
-out:
-       mutex_unlock(&tc35892->lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(tc35892_set_bits);
-
-static struct resource gpio_resources[] = {
-       {
-               .start  = TC35892_INT_GPIIRQ,
-               .end    = TC35892_INT_GPIIRQ,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct mfd_cell tc35892_devs[] = {
-       {
-               .name           = "tc35892-gpio",
-               .num_resources  = ARRAY_SIZE(gpio_resources),
-               .resources      = &gpio_resources[0],
-       },
-};
-
-static irqreturn_t tc35892_irq(int irq, void *data)
-{
-       struct tc35892 *tc35892 = data;
-       int status;
-
-       status = tc35892_reg_read(tc35892, TC35892_IRQST);
-       if (status < 0)
-               return IRQ_NONE;
-
-       while (status) {
-               int bit = __ffs(status);
-
-               handle_nested_irq(tc35892->irq_base + bit);
-               status &= ~(1 << bit);
-       }
-
-       /*
-        * A dummy read or write (to any register) appears to be necessary to
-        * have the last interrupt clear (for example, GPIO IC write) take
-        * effect.
-        */
-       tc35892_reg_read(tc35892, TC35892_IRQST);
-
-       return IRQ_HANDLED;
-}
-
-static void tc35892_irq_dummy(unsigned int irq)
-{
-       /* No mask/unmask at this level */
-}
-
-static struct irq_chip tc35892_irq_chip = {
-       .name   = "tc35892",
-       .mask   = tc35892_irq_dummy,
-       .unmask = tc35892_irq_dummy,
-};
-
-static int tc35892_irq_init(struct tc35892 *tc35892)
-{
-       int base = tc35892->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
-               set_irq_chip_data(irq, tc35892);
-               set_irq_chip_and_handler(irq, &tc35892_irq_chip,
-                                        handle_edge_irq);
-               set_irq_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               set_irq_noprobe(irq);
-#endif
-       }
-
-       return 0;
-}
-
-static void tc35892_irq_remove(struct tc35892 *tc35892)
-{
-       int base = tc35892->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, 0);
-#endif
-               set_irq_chip_and_handler(irq, NULL, NULL);
-               set_irq_chip_data(irq, NULL);
-       }
-}
-
-static int tc35892_chip_init(struct tc35892 *tc35892)
-{
-       int manf, ver, ret;
-
-       manf = tc35892_reg_read(tc35892, TC35892_MANFCODE);
-       if (manf < 0)
-               return manf;
-
-       ver = tc35892_reg_read(tc35892, TC35892_VERSION);
-       if (ver < 0)
-               return ver;
-
-       if (manf != TC35892_MANFCODE_MAGIC) {
-               dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf);
-               return -EINVAL;
-       }
-
-       dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
-
-       /* Put everything except the IRQ module into reset */
-       ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL,
-                               TC35892_RSTCTRL_TIMRST
-                               | TC35892_RSTCTRL_ROTRST
-                               | TC35892_RSTCTRL_KBDRST
-                               | TC35892_RSTCTRL_GPIRST);
-       if (ret < 0)
-               return ret;
-
-       /* Clear the reset interrupt. */
-       return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1);
-}
-
-static int __devinit tc35892_probe(struct i2c_client *i2c,
-                                  const struct i2c_device_id *id)
-{
-       struct tc35892_platform_data *pdata = i2c->dev.platform_data;
-       struct tc35892 *tc35892;
-       int ret;
-
-       if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
-                                    | I2C_FUNC_SMBUS_I2C_BLOCK))
-               return -EIO;
-
-       tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL);
-       if (!tc35892)
-               return -ENOMEM;
-
-       mutex_init(&tc35892->lock);
-
-       tc35892->dev = &i2c->dev;
-       tc35892->i2c = i2c;
-       tc35892->pdata = pdata;
-       tc35892->irq_base = pdata->irq_base;
-       tc35892->num_gpio = id->driver_data;
-
-       i2c_set_clientdata(i2c, tc35892);
-
-       ret = tc35892_chip_init(tc35892);
-       if (ret)
-               goto out_free;
-
-       ret = tc35892_irq_init(tc35892);
-       if (ret)
-               goto out_free;
-
-       ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq,
-                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                  "tc35892", tc35892);
-       if (ret) {
-               dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret);
-               goto out_removeirq;
-       }
-
-       ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs,
-                             ARRAY_SIZE(tc35892_devs), NULL,
-                             tc35892->irq_base);
-       if (ret) {
-               dev_err(tc35892->dev, "failed to add children\n");
-               goto out_freeirq;
-       }
-
-       return 0;
-
-out_freeirq:
-       free_irq(tc35892->i2c->irq, tc35892);
-out_removeirq:
-       tc35892_irq_remove(tc35892);
-out_free:
-       kfree(tc35892);
-       return ret;
-}
-
-static int __devexit tc35892_remove(struct i2c_client *client)
-{
-       struct tc35892 *tc35892 = i2c_get_clientdata(client);
-
-       mfd_remove_devices(tc35892->dev);
-
-       free_irq(tc35892->i2c->irq, tc35892);
-       tc35892_irq_remove(tc35892);
-
-       kfree(tc35892);
-
-       return 0;
-}
-
-static const struct i2c_device_id tc35892_id[] = {
-       { "tc35892", 24 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, tc35892_id);
-
-static struct i2c_driver tc35892_driver = {
-       .driver.name    = "tc35892",
-       .driver.owner   = THIS_MODULE,
-       .probe          = tc35892_probe,
-       .remove         = __devexit_p(tc35892_remove),
-       .id_table       = tc35892_id,
-};
-
-static int __init tc35892_init(void)
-{
-       return i2c_add_driver(&tc35892_driver);
-}
-subsys_initcall(tc35892_init);
-
-static void __exit tc35892_exit(void)
-{
-       i2c_del_driver(&tc35892_driver);
-}
-module_exit(tc35892_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TC35892 MFD core driver");
-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
new file mode 100644 (file)
index 0000000..729dbee
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tc3589x.h>
+
+#define TC3589x_CLKMODE_MODCTL_SLEEP           0x0
+#define TC3589x_CLKMODE_MODCTL_OPERATION       (1 << 0)
+
+/**
+ * tc3589x_reg_read() - read a single TC3589x register
+ * @tc3589x:   Device to read from
+ * @reg:       Register to read
+ */
+int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg);
+       if (ret < 0)
+               dev_err(tc3589x->dev, "failed to read reg %#x: %d\n",
+                       reg, ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_reg_read);
+
+/**
+ * tc3589x_reg_read() - write a single TC3589x register
+ * @tc3589x:   Device to write to
+ * @reg:       Register to read
+ * @data:      Value to write
+ */
+int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data)
+{
+       int ret;
+
+       ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data);
+       if (ret < 0)
+               dev_err(tc3589x->dev, "failed to write reg %#x: %d\n",
+                       reg, ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_reg_write);
+
+/**
+ * tc3589x_block_read() - read multiple TC3589x registers
+ * @tc3589x:   Device to read from
+ * @reg:       First register
+ * @length:    Number of registers
+ * @values:    Buffer to write to
+ */
+int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values)
+{
+       int ret;
+
+       ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values);
+       if (ret < 0)
+               dev_err(tc3589x->dev, "failed to read regs %#x: %d\n",
+                       reg, ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_block_read);
+
+/**
+ * tc3589x_block_write() - write multiple TC3589x registers
+ * @tc3589x:   Device to write to
+ * @reg:       First register
+ * @length:    Number of registers
+ * @values:    Values to write
+ */
+int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
+                       const u8 *values)
+{
+       int ret;
+
+       ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length,
+                                            values);
+       if (ret < 0)
+               dev_err(tc3589x->dev, "failed to write regs %#x: %d\n",
+                       reg, ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_block_write);
+
+/**
+ * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register
+ * @tc3589x:   Device to write to
+ * @reg:       Register to write
+ * @mask:      Mask of bits to set
+ * @values:    Value to set
+ */
+int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
+{
+       int ret;
+
+       mutex_lock(&tc3589x->lock);
+
+       ret = tc3589x_reg_read(tc3589x, reg);
+       if (ret < 0)
+               goto out;
+
+       ret &= ~mask;
+       ret |= val;
+
+       ret = tc3589x_reg_write(tc3589x, reg, ret);
+
+out:
+       mutex_unlock(&tc3589x->lock);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tc3589x_set_bits);
+
+static struct resource gpio_resources[] = {
+       {
+               .start  = TC3589x_INT_GPIIRQ,
+               .end    = TC3589x_INT_GPIIRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource keypad_resources[] = {
+       {
+               .start  = TC3589x_INT_KBDIRQ,
+               .end    = TC3589x_INT_KBDIRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct mfd_cell tc3589x_dev_gpio[] = {
+       {
+               .name           = "tc3589x-gpio",
+               .num_resources  = ARRAY_SIZE(gpio_resources),
+               .resources      = &gpio_resources[0],
+       },
+};
+
+static struct mfd_cell tc3589x_dev_keypad[] = {
+       {
+               .name           = "tc3589x-keypad",
+               .num_resources  = ARRAY_SIZE(keypad_resources),
+               .resources      = &keypad_resources[0],
+       },
+};
+
+static irqreturn_t tc3589x_irq(int irq, void *data)
+{
+       struct tc3589x *tc3589x = data;
+       int status;
+
+again:
+       status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
+       if (status < 0)
+               return IRQ_NONE;
+
+       while (status) {
+               int bit = __ffs(status);
+
+               handle_nested_irq(tc3589x->irq_base + bit);
+               status &= ~(1 << bit);
+       }
+
+       /*
+        * A dummy read or write (to any register) appears to be necessary to
+        * have the last interrupt clear (for example, GPIO IC write) take
+        * effect. In such a case, recheck for any interrupt which is still
+        * pending.
+        */
+       status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
+       if (status)
+               goto again;
+
+       return IRQ_HANDLED;
+}
+
+static int tc3589x_irq_init(struct tc3589x *tc3589x)
+{
+       int base = tc3589x->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
+               set_irq_chip_data(irq, tc3589x);
+               set_irq_chip_and_handler(irq, &dummy_irq_chip,
+                                        handle_edge_irq);
+               set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, IRQF_VALID);
+#else
+               set_irq_noprobe(irq);
+#endif
+       }
+
+       return 0;
+}
+
+static void tc3589x_irq_remove(struct tc3589x *tc3589x)
+{
+       int base = tc3589x->irq_base;
+       int irq;
+
+       for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
+#ifdef CONFIG_ARM
+               set_irq_flags(irq, 0);
+#endif
+               set_irq_chip_and_handler(irq, NULL, NULL);
+               set_irq_chip_data(irq, NULL);
+       }
+}
+
+static int tc3589x_chip_init(struct tc3589x *tc3589x)
+{
+       int manf, ver, ret;
+
+       manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE);
+       if (manf < 0)
+               return manf;
+
+       ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION);
+       if (ver < 0)
+               return ver;
+
+       if (manf != TC3589x_MANFCODE_MAGIC) {
+               dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf);
+               return -EINVAL;
+       }
+
+       dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
+
+       /*
+        * Put everything except the IRQ module into reset;
+        * also spare the GPIO module for any pin initialization
+        * done during pre-kernel boot
+        */
+       ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL,
+                               TC3589x_RSTCTRL_TIMRST
+                               | TC3589x_RSTCTRL_ROTRST
+                               | TC3589x_RSTCTRL_KBDRST);
+       if (ret < 0)
+               return ret;
+
+       /* Clear the reset interrupt. */
+       return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
+}
+
+static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
+{
+       int ret = 0;
+       unsigned int blocks = tc3589x->pdata->block;
+
+       if (blocks & TC3589x_BLOCK_GPIO) {
+               ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
+                               ARRAY_SIZE(tc3589x_dev_gpio), NULL,
+                               tc3589x->irq_base);
+               if (ret) {
+                       dev_err(tc3589x->dev, "failed to add gpio child\n");
+                       return ret;
+               }
+               dev_info(tc3589x->dev, "added gpio block\n");
+       }
+
+       if (blocks & TC3589x_BLOCK_KEYPAD) {
+               ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
+                               ARRAY_SIZE(tc3589x_dev_keypad), NULL,
+                               tc3589x->irq_base);
+               if (ret) {
+                       dev_err(tc3589x->dev, "failed to keypad child\n");
+                       return ret;
+               }
+               dev_info(tc3589x->dev, "added keypad block\n");
+       }
+
+       return ret;
+}
+
+static int __devinit tc3589x_probe(struct i2c_client *i2c,
+                                  const struct i2c_device_id *id)
+{
+       struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
+       struct tc3589x *tc3589x;
+       int ret;
+
+       if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
+                                    | I2C_FUNC_SMBUS_I2C_BLOCK))
+               return -EIO;
+
+       tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL);
+       if (!tc3589x)
+               return -ENOMEM;
+
+       mutex_init(&tc3589x->lock);
+
+       tc3589x->dev = &i2c->dev;
+       tc3589x->i2c = i2c;
+       tc3589x->pdata = pdata;
+       tc3589x->irq_base = pdata->irq_base;
+       tc3589x->num_gpio = id->driver_data;
+
+       i2c_set_clientdata(i2c, tc3589x);
+
+       ret = tc3589x_chip_init(tc3589x);
+       if (ret)
+               goto out_free;
+
+       ret = tc3589x_irq_init(tc3589x);
+       if (ret)
+               goto out_free;
+
+       ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  "tc3589x", tc3589x);
+       if (ret) {
+               dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
+               goto out_removeirq;
+       }
+
+       ret = tc3589x_device_init(tc3589x);
+       if (ret) {
+               dev_err(tc3589x->dev, "failed to add child devices\n");
+               goto out_freeirq;
+       }
+
+       return 0;
+
+out_freeirq:
+       free_irq(tc3589x->i2c->irq, tc3589x);
+out_removeirq:
+       tc3589x_irq_remove(tc3589x);
+out_free:
+       kfree(tc3589x);
+       return ret;
+}
+
+static int __devexit tc3589x_remove(struct i2c_client *client)
+{
+       struct tc3589x *tc3589x = i2c_get_clientdata(client);
+
+       mfd_remove_devices(tc3589x->dev);
+
+       free_irq(tc3589x->i2c->irq, tc3589x);
+       tc3589x_irq_remove(tc3589x);
+
+       kfree(tc3589x);
+
+       return 0;
+}
+
+static int tc3589x_suspend(struct device *dev)
+{
+       struct tc3589x *tc3589x = dev_get_drvdata(dev);
+       struct i2c_client *client = tc3589x->i2c;
+       int ret = 0;
+
+       /* put the system to sleep mode */
+       if (!device_may_wakeup(&client->dev))
+               ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
+                               TC3589x_CLKMODE_MODCTL_SLEEP);
+
+       return ret;
+}
+
+static int tc3589x_resume(struct device *dev)
+{
+       struct tc3589x *tc3589x = dev_get_drvdata(dev);
+       struct i2c_client *client = tc3589x->i2c;
+       int ret = 0;
+
+       /* enable the system into operation */
+       if (!device_may_wakeup(&client->dev))
+               ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
+                               TC3589x_CLKMODE_MODCTL_OPERATION);
+
+       return ret;
+}
+
+static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend,
+                                               tc3589x_resume);
+
+static const struct i2c_device_id tc3589x_id[] = {
+       { "tc3589x", 24 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tc3589x_id);
+
+static struct i2c_driver tc3589x_driver = {
+       .driver.name    = "tc3589x",
+       .driver.owner   = THIS_MODULE,
+#ifdef CONFIG_PM
+       .driver.pm      = &tc3589x_dev_pm_ops,
+#endif
+       .probe          = tc3589x_probe,
+       .remove         = __devexit_p(tc3589x_remove),
+       .id_table       = tc3589x_id,
+};
+
+static int __init tc3589x_init(void)
+{
+       return i2c_add_driver(&tc3589x_driver);
+}
+subsys_initcall(tc3589x_init);
+
+static void __exit tc3589x_exit(void)
+{
+       i2c_del_driver(&tc3589x_driver);
+}
+module_exit(tc3589x_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TC3589x MFD core driver");
+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
index dd90880048cf3fe2f8d209ad654159565a5987e4..d8ae634d347ebc4262704188adb1dea943c909e6 100644 (file)
@@ -51,7 +51,7 @@ struct pxa2xx_flash_info {
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 
-static int __init pxa2xx_flash_probe(struct platform_device *pdev)
+static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
        struct flash_platform_data *flash = pdev->dev.platform_data;
        struct pxa2xx_flash_info *info;
index cd41c58b5bbd50f8ed905a1a6da71dedc5cfca7e..15682ec8530ed008f8f3f8ddbd16e577306a6407 100644 (file)
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#define CONFIG_MTD_NAND_OMAP_HWECC
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
index c6e86315b3f8df37aa2ac1a767ac46fc1b5eba60..2e2b76258ab42cbc6b0dc73f70bd9547a5846857 100644 (file)
@@ -381,11 +381,11 @@ static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
        __b44_set_flow_ctrl(bp, pause_enab);
 }
 
-#ifdef SSB_DRIVER_MIPS
-extern char *nvram_get(char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 static void b44_wap54g10_workaround(struct b44 *bp)
 {
-       const char *str;
+       char buf[20];
        u32 val;
        int err;
 
@@ -394,10 +394,9 @@ static void b44_wap54g10_workaround(struct b44 *bp)
         * see https://dev.openwrt.org/ticket/146
         * check and reset bit "isolate"
         */
-       str = nvram_get("boardnum");
-       if (!str)
+       if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
                return;
-       if (simple_strtoul(str, NULL, 0) == 2) {
+       if (simple_strtoul(buf, NULL, 0) == 2) {
                err = __b44_readphy(bp, 0, MII_BMCR, &val);
                if (err)
                        goto error;
index 36eca1ce75d4e29a4c41bbf285931ce003a6a92a..e4465d222a7d019654c27c5f4d3db89067f89cf8 100644 (file)
@@ -1235,7 +1235,7 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
 
                i = 0;
                netdev_for_each_mc_addr(ha, netdev)
-                       memcpy(req->mac[i].byte, ha->addr, ETH_ALEN);
+                       memcpy(req->mac[i++].byte, ha->addr, ETH_ALEN);
        } else {
                req->promiscuous = 1;
        }
index 863e73a85fbe0ef4cd48ebac5cd5e95846397ebc..d255428122fc0b87d3e4ff2925410b5b2d5f6a47 100644 (file)
@@ -20,8 +20,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.60.00-4"
-#define DRV_MODULE_RELDATE      "2010/11/01"
+#define DRV_MODULE_VERSION      "1.60.01-0"
+#define DRV_MODULE_RELDATE      "2010/11/12"
 #define BNX2X_BC_VER            0x040200
 
 #define BNX2X_MULTI_QUEUE
index 94d5f59d5a6f0a1de6dd8cc5ad44fc2083649b98..0af361e4e3d16ab83d8c3067396f63c5d46d1cb1 100644 (file)
@@ -1782,15 +1782,15 @@ exit_lbl:
 }
 #endif
 
-static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb,
-                                    struct eth_tx_parse_bd_e2 *pbd,
-                                    u32 xmit_type)
+static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
+                                       u32 xmit_type)
 {
-       pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) <<
-               ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT;
+       *parsing_data |= (skb_shinfo(skb)->gso_size <<
+                             ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT) &
+                             ETH_TX_PARSE_BD_E2_LSO_MSS;
        if ((xmit_type & XMIT_GSO_V6) &&
            (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
-               pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
+               *parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
 }
 
 /**
@@ -1835,15 +1835,15 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
  * @return header len
  */
 static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
-       struct eth_tx_parse_bd_e2 *pbd,
-       u32 xmit_type)
+       u32 *parsing_data, u32 xmit_type)
 {
-       pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT;
+       *parsing_data |= ((tcp_hdrlen(skb)/4) <<
+               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
 
-       pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) -
-                                         skb->data) / 2) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT;
+       *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
+               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
+               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
 
        return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
 }
@@ -1912,6 +1912,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
        struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
        struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
+       u32 pbd_e2_parsing_data = 0;
        u16 pkt_prod, bd_prod;
        int nbd, fp_index;
        dma_addr_t mapping;
@@ -2033,8 +2034,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
                /* Set PBD in checksum offload case */
                if (xmit_type & XMIT_CSUM)
-                       hlen = bnx2x_set_pbd_csum_e2(bp,
-                                                    skb, pbd_e2, xmit_type);
+                       hlen = bnx2x_set_pbd_csum_e2(bp, skb,
+                                                    &pbd_e2_parsing_data,
+                                                    xmit_type);
        } else {
                pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
                memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
@@ -2076,10 +2078,18 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
                                                 hlen, bd_prod, ++nbd);
                if (CHIP_IS_E2(bp))
-                       bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type);
+                       bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
+                                            xmit_type);
                else
                        bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
        }
+
+       /* Set the PBD's parsing_data field if not zero
+        * (for the chips newer than 57711).
+        */
+       if (pbd_e2_parsing_data)
+               pbd_e2->parsing_data = cpu_to_le32(pbd_e2_parsing_data);
+
        tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
 
        /* Handle fragmented skb */
index a306b0e46b613417c630e79398c5f8250204195d..66df29fcf7516e45b7794fee314d0122fca6d42b 100644 (file)
@@ -838,7 +838,7 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
 /****************************************************************************
 * SRC initializations
 ****************************************************************************/
-
+#ifdef BCM_CNIC
 /* called during init func stage */
 static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                              dma_addr_t t2_mapping, int src_cid_count)
@@ -862,5 +862,5 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                    U64_HI((u64)t2_mapping +
                           (src_cid_count-1) * sizeof(struct src_ent)));
 }
-
+#endif
 #endif /* BNX2X_INIT_OPS_H */
index 71a169740d05daf463b04f2ff591a943f8c1847e..d0ea760ce419f0ae8040bf880cd80013c651a93a 100644 (file)
@@ -171,7 +171,7 @@ MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link
 /*----------------------------- Global variables ----------------------------*/
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-cpumask_var_t netpoll_block_tx;
+atomic_t netpoll_block_tx = ATOMIC_INIT(0);
 #endif
 
 static const char * const version =
@@ -1576,7 +1576,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        /* If this is the first slave, then we need to set the master's hardware
         * address to be the same as the slave's. */
-       if (bond->slave_cnt == 0)
+       if (is_zero_ether_addr(bond->dev->dev_addr))
                memcpy(bond->dev->dev_addr, slave_dev->dev_addr,
                       slave_dev->addr_len);
 
@@ -5299,13 +5299,6 @@ static int __init bonding_init(void)
        if (res)
                goto out;
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       if (!alloc_cpumask_var(&netpoll_block_tx, GFP_KERNEL)) {
-               res = -ENOMEM;
-               goto out;
-       }
-#endif
-
        res = register_pernet_subsys(&bond_net_ops);
        if (res)
                goto out;
@@ -5334,9 +5327,6 @@ err:
        rtnl_link_unregister(&bond_link_ops);
 err_link:
        unregister_pernet_subsys(&bond_net_ops);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       free_cpumask_var(netpoll_block_tx);
-#endif
        goto out;
 
 }
@@ -5353,7 +5343,10 @@ static void __exit bonding_exit(void)
        unregister_pernet_subsys(&bond_net_ops);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       free_cpumask_var(netpoll_block_tx);
+       /*
+        * Make sure we don't have an imbalance on our netpoll blocking
+        */
+       WARN_ON(atomic_read(&netpoll_block_tx));
 #endif
 }
 
index 4eedb12df6caf2e4676cbe11e2134e97ec01def1..c2f081352a037894d6e8238ccb70c39e796c4a69 100644 (file)
 
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-extern cpumask_var_t netpoll_block_tx;
+extern atomic_t netpoll_block_tx;
 
 static inline void block_netpoll_tx(void)
 {
-       preempt_disable();
-       BUG_ON(cpumask_test_and_set_cpu(smp_processor_id(),
-                                       netpoll_block_tx));
+       atomic_inc(&netpoll_block_tx);
 }
 
 static inline void unblock_netpoll_tx(void)
 {
-       BUG_ON(!cpumask_test_and_clear_cpu(smp_processor_id(),
-                                          netpoll_block_tx));
-       preempt_enable();
+       atomic_dec(&netpoll_block_tx);
 }
 
 static inline int is_netpoll_tx_blocked(struct net_device *dev)
 {
        if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
-               return cpumask_test_cpu(smp_processor_id(), netpoll_block_tx);
+               return atomic_read(&netpoll_block_tx);
        return 0;
 }
 #else
index 1cd90da86f130ea588070634db35959a47ca7b87..5f771ab712c4c3705eae9af9dde20b88948a8c71 100644 (file)
@@ -5,13 +5,13 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
 
 #include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <mach/mbox.h>
+#include <mach/mbox-db5500.h>
 #include <net/caif/caif_shm.h>
 
 MODULE_LICENSE("GPL");
index 19f9c065666745633752c3e59b312d2a4e9812c0..80511167f35bd4bcfb53cf424eb58ff4174a558b 100644 (file)
@@ -6,7 +6,7 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
 
 #include <linux/spinlock.h>
 #include <linux/sched.h>
index bb813d94aea8ef5ae11db63ce6ac795fd0a62c39..e97521c801ea6e4a90714bd2038d4c0610b8806a 100644 (file)
@@ -2408,7 +2408,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
                if (index < NEXACT_MAC)
                        ret++;
                else if (hash)
-                       *hash |= (1 << hash_mac_addr(addr[i]));
+                       *hash |= (1ULL << hash_mac_addr(addr[i]));
        }
        return ret;
 }
index d887a76cd39dad036eb289d88f5a666d898eb63a..6bf464afa90ed1a60cf06bb91f31964cf82a7e5d 100644 (file)
@@ -2269,6 +2269,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
 {
        struct sge *s = &adapter->sge;
        int q10g, n10g, qidx, pidx, qs;
+       size_t iqe_size;
 
        /*
         * We should not be called till we know how many Queue Sets we can
@@ -2312,6 +2313,13 @@ static void __devinit cfg_queues(struct adapter *adapter)
        }
        s->ethqsets = qidx;
 
+       /*
+        * The Ingress Queue Entry Size for our various Response Queues needs
+        * to be big enough to accommodate the largest message we can receive
+        * from the chip/firmware; which is 64 bytes ...
+        */
+       iqe_size = 64;
+
        /*
         * Set up default Queue Set parameters ...  Start off with the
         * shortest interrupt holdoff timer.
@@ -2320,7 +2328,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
                struct sge_eth_rxq *rxq = &s->ethrxq[qs];
                struct sge_eth_txq *txq = &s->ethtxq[qs];
 
-               init_rspq(&rxq->rspq, 0, 0, 1024, L1_CACHE_BYTES);
+               init_rspq(&rxq->rspq, 0, 0, 1024, iqe_size);
                rxq->fl.size = 72;
                txq->q.size = 1024;
        }
@@ -2329,8 +2337,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
         * The firmware event queue is used for link state changes and
         * notifications of TX DMA completions.
         */
-       init_rspq(&s->fw_evtq, SGE_TIMER_RSTRT_CNTR, 0, 512,
-                 L1_CACHE_BYTES);
+       init_rspq(&s->fw_evtq, SGE_TIMER_RSTRT_CNTR, 0, 512, iqe_size);
 
        /*
         * The forwarded interrupt queue is used when we're in MSI interrupt
@@ -2346,7 +2353,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
         * any time ...
         */
        init_rspq(&s->intrq, SGE_TIMER_RSTRT_CNTR, 0, MSIX_ENTRIES + 1,
-                 L1_CACHE_BYTES);
+                 iqe_size);
 }
 
 /*
index 75b099ce49c9b47e361adc66da99d148b58640f3..1f37ee6b2a2626282fd5a772cc21f821321b9379 100644 (file)
@@ -261,6 +261,13 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
 
 }
 
+static int ehea_set_flags(struct net_device *dev, u32 data)
+{
+       return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO
+                                       | ETH_FLAG_TXVLAN
+                                       | ETH_FLAG_RXVLAN);
+}
+
 const struct ethtool_ops ehea_ethtool_ops = {
        .get_settings = ehea_get_settings,
        .get_drvinfo = ehea_get_drvinfo,
@@ -273,6 +280,8 @@ const struct ethtool_ops ehea_ethtool_ops = {
        .get_ethtool_stats = ehea_get_ethtool_stats,
        .get_rx_csum = ehea_get_rx_csum,
        .set_settings = ehea_set_settings,
+       .get_flags = ethtool_op_get_flags,
+       .set_flags = ehea_set_flags,
        .nway_reset = ehea_nway_reset,          /* Restart autonegotiation */
 };
 
index 3d0af08483a16792874d46958c2821641f5b7f97..b95f087cd5a9c4a51525718e90ba65b56cf81b99 100644 (file)
@@ -683,7 +683,7 @@ static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
        int vlan_extracted = ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
                              pr->port->vgrp);
 
-       if (use_lro) {
+       if (skb->dev->features & NETIF_F_LRO) {
                if (vlan_extracted)
                        lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb,
                                                     pr->port->vgrp,
@@ -787,7 +787,7 @@ static int ehea_proc_rwqes(struct net_device *dev,
                }
                cqe = ehea_poll_rq1(qp, &wqe_index);
        }
-       if (use_lro)
+       if (dev->features & NETIF_F_LRO)
                lro_flush_all(&pr->lro_mgr);
 
        pr->rx_packets += processed;
@@ -3278,6 +3278,9 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
                      | NETIF_F_LLTX;
        dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
+       if (use_lro)
+               dev->features |= NETIF_F_LRO;
+
        INIT_WORK(&port->reset_task, ehea_reset_port);
 
        ret = register_netdev(dev);
index a466ef91dd4351d58f37e4ed5b443395ce4725e6..aa28b270c045e1a32562be18f68a1ec0449f276f 100644 (file)
@@ -1962,7 +1962,8 @@ static void enic_poll_controller(struct net_device *netdev)
        case VNIC_DEV_INTR_MODE_MSIX:
                for (i = 0; i < enic->rq_count; i++) {
                        intr = enic_msix_rq_intr(enic, i);
-                       enic_isr_msix_rq(enic->msix_entry[intr].vector, enic);
+                       enic_isr_msix_rq(enic->msix_entry[intr].vector,
+                               &enic->napi[i]);
                }
                intr = enic_msix_wq_intr(enic, i);
                enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
index ab9f675c5b8b8b86473d07b60b3ad933523b3ab5..fe337bd121aa74d3eb60cf866e31b8f76fa84573 100644 (file)
@@ -104,6 +104,8 @@ static void ri_tasklet(unsigned long dev)
                        rcu_read_unlock();
                        dev_kfree_skb(skb);
                        stats->tx_dropped++;
+                       if (skb_queue_len(&dp->tq) != 0)
+                               goto resched;
                        break;
                }
                rcu_read_unlock();
index fbad4d819608f234d0eff25175bccf9a8545c20b..eee0b298bd3616558ca8d9f5cf44a02fe95c68e7 100644 (file)
@@ -4771,6 +4771,9 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
                adapter->rx_ring[i] = NULL;
        }
 
+       adapter->num_tx_queues = 0;
+       adapter->num_rx_queues = 0;
+
        ixgbe_free_q_vectors(adapter);
        ixgbe_reset_interrupt_capability(adapter);
 }
index cb3d13e4e074097a4b89b9f0315f3d64b6ad68ff..35fda5ac8120c056eb94d0f14bea376494d2d59c 100644 (file)
@@ -64,7 +64,7 @@ config BCM63XX_PHY
 config ICPLUS_PHY
        tristate "Drivers for ICPlus PHYs"
        ---help---
-         Currently supports the IP175C PHY.
+         Currently supports the IP175C and IP1001 PHYs.
 
 config REALTEK_PHY
        tristate "Drivers for Realtek PHYs"
index c1d2d251fe8bfcef7114fd57b1018c70697006f5..9a09e24c30bc2e222974b481f76d219ed6a22cd6 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_DESCRIPTION("ICPlus IP175C/IC1001 PHY drivers");
 MODULE_AUTHOR("Michael Barkowski");
 MODULE_LICENSE("GPL");
 
@@ -89,6 +89,33 @@ static int ip175c_config_init(struct phy_device *phydev)
        return 0;
 }
 
+static int ip1001_config_init(struct phy_device *phydev)
+{
+       int err, value;
+
+       /* Software Reset PHY */
+       value = phy_read(phydev, MII_BMCR);
+       value |= BMCR_RESET;
+       err = phy_write(phydev, MII_BMCR, value);
+       if (err < 0)
+               return err;
+
+       do {
+               value = phy_read(phydev, MII_BMCR);
+       } while (value & BMCR_RESET);
+
+       /* Additional delay (2ns) used to adjust RX clock phase
+        * at GMII/ RGMII interface */
+       value = phy_read(phydev, 16);
+       value |= 0x3;
+
+       err = phy_write(phydev, 16, value);
+       if (err < 0)
+               return err;
+
+       return err;
+}
+
 static int ip175c_read_status(struct phy_device *phydev)
 {
        if (phydev->addr == 4) /* WAN port */
@@ -121,21 +148,43 @@ static struct phy_driver ip175c_driver = {
        .driver         = { .owner = THIS_MODULE,},
 };
 
-static int __init ip175c_init(void)
+static struct phy_driver ip1001_driver = {
+       .phy_id         = 0x02430d90,
+       .name           = "ICPlus IP1001",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_GBIT_FEATURES | SUPPORTED_Pause |
+                         SUPPORTED_Asym_Pause,
+       .config_init    = &ip1001_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .suspend        = genphy_suspend,
+       .resume         = genphy_resume,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init icplus_init(void)
 {
+       int ret = 0;
+
+       ret = phy_driver_register(&ip1001_driver);
+       if (ret < 0)
+               return -ENODEV;
+
        return phy_driver_register(&ip175c_driver);
 }
 
-static void __exit ip175c_exit(void)
+static void __exit icplus_exit(void)
 {
+       phy_driver_unregister(&ip1001_driver);
        phy_driver_unregister(&ip175c_driver);
 }
 
-module_init(ip175c_init);
-module_exit(ip175c_exit);
+module_init(icplus_init);
+module_exit(icplus_exit);
 
 static struct mdio_device_id __maybe_unused icplus_tbl[] = {
        { 0x02430d80, 0x0ffffff0 },
+       { 0x02430d90, 0x0ffffff0 },
        { }
 };
 
index d72fb0519a2aa674a8757f5146b0df19655d9749..78c0e3c9b2b5fcb8d42fb910ab2416e4db787dc7 100644 (file)
@@ -948,7 +948,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
 
 abort:
        kfree_skb(skb);
-       return 0;
+       return 1;
 }
 
 /************************************************************************
index 22821398fc63765054eff056ab2529beedfb30fc..9787dff90d3fa18a3e70cbdac43fa73062202b33 100644 (file)
@@ -2083,6 +2083,7 @@ struct ql_adapter {
        u32 mailbox_in;
        u32 mailbox_out;
        struct mbox_params idc_mbc;
+       struct mutex    mpi_mutex;
 
        int tx_ring_size;
        int rx_ring_size;
index 528eaef5308fa59460c8697ffc4fc0400d74a6cb..2555b1d34f346d691f904bb3f8593a3933f2b6fc 100644 (file)
@@ -4629,6 +4629,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work);
        INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log);
        init_completion(&qdev->ide_completion);
+       mutex_init(&qdev->mpi_mutex);
 
        if (!cards_found) {
                dev_info(&pdev->dev, "%s\n", DRV_STRING);
index 0e7c7c7ee1647006baf561ffd90308290fbd2399..a2e919bcb3c6b616250eeafb4e76ae7a5921f50e 100644 (file)
@@ -534,6 +534,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
        int status;
        unsigned long count;
 
+       mutex_lock(&qdev->mpi_mutex);
 
        /* Begin polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
@@ -603,6 +604,7 @@ done:
 end:
        /* End polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
+       mutex_unlock(&qdev->mpi_mutex);
        return status;
 }
 
@@ -1099,9 +1101,7 @@ int ql_wait_fifo_empty(struct ql_adapter *qdev)
 static int ql_set_port_cfg(struct ql_adapter *qdev)
 {
        int status;
-       rtnl_lock();
        status = ql_mb_set_port_cfg(qdev);
-       rtnl_unlock();
        if (status)
                return status;
        status = ql_idc_wait(qdev);
@@ -1122,9 +1122,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work)
            container_of(work, struct ql_adapter, mpi_port_cfg_work.work);
        int status;
 
-       rtnl_lock();
        status = ql_mb_get_port_cfg(qdev);
-       rtnl_unlock();
        if (status) {
                netif_err(qdev, drv, qdev->ndev,
                          "Bug: Failed to get port config data.\n");
@@ -1167,7 +1165,6 @@ void ql_mpi_idc_work(struct work_struct *work)
        u32 aen;
        int timeout;
 
-       rtnl_lock();
        aen = mbcp->mbox_out[1] >> 16;
        timeout = (mbcp->mbox_out[1] >> 8) & 0xf;
 
@@ -1231,7 +1228,6 @@ void ql_mpi_idc_work(struct work_struct *work)
                }
                break;
        }
-       rtnl_unlock();
 }
 
 void ql_mpi_work(struct work_struct *work)
@@ -1242,7 +1238,7 @@ void ql_mpi_work(struct work_struct *work)
        struct mbox_params *mbcp = &mbc;
        int err = 0;
 
-       rtnl_lock();
+       mutex_lock(&qdev->mpi_mutex);
        /* Begin polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
 
@@ -1259,7 +1255,7 @@ void ql_mpi_work(struct work_struct *work)
 
        /* End polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
-       rtnl_unlock();
+       mutex_unlock(&qdev->mpi_mutex);
        ql_enable_completion_interrupt(qdev, 0);
 }
 
index 7d33ef4bcb4a1d6ca7125d6780e173889ebbb0d8..53b13deade9528539ea2dcaf5fe268b0e1ceabda 100644 (file)
@@ -744,26 +744,36 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
        mdio_write(ioaddr, MII_BMCR, val & 0xffff);
 }
 
-static void rtl8169_check_link_status(struct net_device *dev,
+static void __rtl8169_check_link_status(struct net_device *dev,
                                      struct rtl8169_private *tp,
-                                     void __iomem *ioaddr)
+                                     void __iomem *ioaddr,
+                                     bool pm)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&tp->lock, flags);
        if (tp->link_ok(ioaddr)) {
                /* This is to cancel a scheduled suspend if there's one. */
-               pm_request_resume(&tp->pci_dev->dev);
+               if (pm)
+                       pm_request_resume(&tp->pci_dev->dev);
                netif_carrier_on(dev);
                netif_info(tp, ifup, dev, "link up\n");
        } else {
                netif_carrier_off(dev);
                netif_info(tp, ifdown, dev, "link down\n");
-               pm_schedule_suspend(&tp->pci_dev->dev, 100);
+               if (pm)
+                       pm_schedule_suspend(&tp->pci_dev->dev, 100);
        }
        spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+static void rtl8169_check_link_status(struct net_device *dev,
+                                     struct rtl8169_private *tp,
+                                     void __iomem *ioaddr)
+{
+       __rtl8169_check_link_status(dev, tp, ioaddr, false);
+}
+
 #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
 
 static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
@@ -4600,7 +4610,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
                }
 
                if (status & LinkChg)
-                       rtl8169_check_link_status(dev, tp, ioaddr);
+                       __rtl8169_check_link_status(dev, tp, ioaddr, true);
 
                /* We need to see the lastest version of tp->intr_mask to
                 * avoid ignoring an MSI interrupt and having to wait for
@@ -4890,11 +4900,7 @@ static int rtl8169_runtime_idle(struct device *device)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rtl8169_private *tp = netdev_priv(dev);
 
-       if (!tp->TxDescArray)
-               return 0;
-
-       rtl8169_check_link_status(dev, tp, tp->mmio_addr);
-       return -EBUSY;
+       return tp->TxDescArray ? -EBUSY : 0;
 }
 
 static const struct dev_pm_ops rtl8169_pm_ops = {
index 05df20e47976cb3965c59c5b227e67877bd2d0c4..fb83cdd946436561dbe645f5d742317fea8cfe91 100644 (file)
@@ -197,7 +197,9 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
 
 static void efx_remove_channels(struct efx_nic *efx);
 static void efx_remove_port(struct efx_nic *efx);
+static void efx_init_napi(struct efx_nic *efx);
 static void efx_fini_napi(struct efx_nic *efx);
+static void efx_fini_napi_channel(struct efx_channel *channel);
 static void efx_fini_struct(struct efx_nic *efx);
 static void efx_start_all(struct efx_nic *efx);
 static void efx_stop_all(struct efx_nic *efx);
@@ -335,8 +337,10 @@ void efx_process_channel_now(struct efx_channel *channel)
 
        /* Disable interrupts and wait for ISRs to complete */
        efx_nic_disable_interrupts(efx);
-       if (efx->legacy_irq)
+       if (efx->legacy_irq) {
                synchronize_irq(efx->legacy_irq);
+               efx->legacy_irq_enabled = false;
+       }
        if (channel->irq)
                synchronize_irq(channel->irq);
 
@@ -351,6 +355,8 @@ void efx_process_channel_now(struct efx_channel *channel)
        efx_channel_processed(channel);
 
        napi_enable(&channel->napi_str);
+       if (efx->legacy_irq)
+               efx->legacy_irq_enabled = true;
        efx_nic_enable_interrupts(efx);
 }
 
@@ -426,6 +432,7 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
 
                *channel = *old_channel;
 
+               channel->napi_dev = NULL;
                memset(&channel->eventq, 0, sizeof(channel->eventq));
 
                rx_queue = &channel->rx_queue;
@@ -736,9 +743,13 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
        if (rc)
                goto rollback;
 
+       efx_init_napi(efx);
+
        /* Destroy old channels */
-       for (i = 0; i < efx->n_channels; i++)
+       for (i = 0; i < efx->n_channels; i++) {
+               efx_fini_napi_channel(other_channel[i]);
                efx_remove_channel(other_channel[i]);
+       }
 out:
        /* Free unused channel structures */
        for (i = 0; i < efx->n_channels; i++)
@@ -1400,6 +1411,8 @@ static void efx_start_all(struct efx_nic *efx)
                efx_start_channel(channel);
        }
 
+       if (efx->legacy_irq)
+               efx->legacy_irq_enabled = true;
        efx_nic_enable_interrupts(efx);
 
        /* Switch to event based MCDI completions after enabling interrupts.
@@ -1460,8 +1473,10 @@ static void efx_stop_all(struct efx_nic *efx)
 
        /* Disable interrupts and wait for ISR to complete */
        efx_nic_disable_interrupts(efx);
-       if (efx->legacy_irq)
+       if (efx->legacy_irq) {
                synchronize_irq(efx->legacy_irq);
+               efx->legacy_irq_enabled = false;
+       }
        efx_for_each_channel(channel, efx) {
                if (channel->irq)
                        synchronize_irq(channel->irq);
@@ -1593,7 +1608,7 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
  *
  **************************************************************************/
 
-static int efx_init_napi(struct efx_nic *efx)
+static void efx_init_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
 
@@ -1602,18 +1617,21 @@ static int efx_init_napi(struct efx_nic *efx)
                netif_napi_add(channel->napi_dev, &channel->napi_str,
                               efx_poll, napi_weight);
        }
-       return 0;
+}
+
+static void efx_fini_napi_channel(struct efx_channel *channel)
+{
+       if (channel->napi_dev)
+               netif_napi_del(&channel->napi_str);
+       channel->napi_dev = NULL;
 }
 
 static void efx_fini_napi(struct efx_nic *efx)
 {
        struct efx_channel *channel;
 
-       efx_for_each_channel(channel, efx) {
-               if (channel->napi_dev)
-                       netif_napi_del(&channel->napi_str);
-               channel->napi_dev = NULL;
-       }
+       efx_for_each_channel(channel, efx)
+               efx_fini_napi_channel(channel);
 }
 
 /**************************************************************************
@@ -2335,9 +2353,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
        if (rc)
                goto fail1;
 
-       rc = efx_init_napi(efx);
-       if (rc)
-               goto fail2;
+       efx_init_napi(efx);
 
        rc = efx->type->init(efx);
        if (rc) {
@@ -2368,7 +2384,6 @@ static int efx_pci_probe_main(struct efx_nic *efx)
        efx->type->fini(efx);
  fail3:
        efx_fini_napi(efx);
- fail2:
        efx_remove_all(efx);
  fail1:
        return rc;
index 0a7e26d73b525b13aba1fc9e234d38a699322f2a..b137c889152b14be6486fe9271f00658f81df031 100644 (file)
@@ -621,6 +621,7 @@ struct efx_filter_state;
  * @pci_dev: The PCI device
  * @type: Controller type attributes
  * @legacy_irq: IRQ number
+ * @legacy_irq_enabled: Are IRQs enabled on NIC (INT_EN_KER register)?
  * @workqueue: Workqueue for port reconfigures and the HW monitor.
  *     Work items do not hold and must not acquire RTNL.
  * @workqueue_name: Name of workqueue
@@ -709,6 +710,7 @@ struct efx_nic {
        struct pci_dev *pci_dev;
        const struct efx_nic_type *type;
        int legacy_irq;
+       bool legacy_irq_enabled;
        struct workqueue_struct *workqueue;
        char workqueue_name[16];
        struct work_struct reset_work;
index 41c36b9a4244b907907936b0a6abeaf8f2a301d1..67cb0c96838caeee1bc0497266ef51dd8e9bb407 100644 (file)
@@ -1418,6 +1418,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
        u32 queues;
        int syserr;
 
+       /* Could this be ours?  If interrupts are disabled then the
+        * channel state may not be valid.
+        */
+       if (!efx->legacy_irq_enabled)
+               return result;
+
        /* Read the ISR which also ACKs the interrupts */
        efx_readd(efx, &reg, FR_BZ_INT_ISR0);
        queues = EFX_EXTRACT_DWORD(reg, 0, 31);
index 06bc6034ce810f49a67a698af524bec91e1eee5f..2114837809e76707e69f41cde38b0a0856ee745a 100644 (file)
@@ -1509,6 +1509,8 @@ static int stmmac_probe(struct net_device *dev)
                pr_warning("\tno valid MAC address;"
                        "please, use ifconfig or nwhwconfig!\n");
 
+       spin_lock_init(&priv->lock);
+
        ret = register_netdev(dev);
        if (ret) {
                pr_err("%s: ERROR %i registering the device\n",
@@ -1520,8 +1522,6 @@ static int stmmac_probe(struct net_device *dev)
            dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
            (dev->features & NETIF_F_HW_CSUM) ? "on" : "off");
 
-       spin_lock_init(&priv->lock);
-
        return ret;
 }
 
index a9f7d5d1a2695f95a968001a93c1449b9ac998be..7064e035757a16b927d35aa61991268089275744 100644 (file)
@@ -688,9 +688,6 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
 
        DMFE_DBUG(0, "dmfe_start_xmit", 0);
 
-       /* Resource flag check */
-       netif_stop_queue(dev);
-
        /* Too large packet check */
        if (skb->len > MAX_PACKET_SIZE) {
                pr_err("big packet = %d\n", (u16)skb->len);
@@ -698,6 +695,9 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
+       /* Resource flag check */
+       netif_stop_queue(dev);
+
        spin_lock_irqsave(&db->lock, flags);
 
        /* No Tx resource check, it never happen nromally */
index 62e9e8dc8190d69314529cd42d0d2b7f06228746..812edf85d6d32b017454f449f4d03e300ed4ec50 100644 (file)
@@ -958,10 +958,6 @@ static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt,
                                /* Packet is complete. Inject into stack. */
                                /* We have IP packet here */
                                odev->skb_rx_buf->protocol = cpu_to_be16(ETH_P_IP);
-                               /* don't check it */
-                               odev->skb_rx_buf->ip_summed =
-                                       CHECKSUM_UNNECESSARY;
-
                                skb_reset_mac_header(odev->skb_rx_buf);
 
                                /* Ship it off to the kernel */
index ea476cbd38b511039c8cb21ecdba7c61c1071ff1..e305274f83fba70c4967b2af57934ec5347a7eea 100644 (file)
@@ -293,6 +293,7 @@ static inline void sca_tx_done(port_t *port)
        struct net_device *dev = port->netdev;
        card_t* card = port->card;
        u8 stat;
+       unsigned count = 0;
 
        spin_lock(&port->lock);
 
@@ -316,10 +317,12 @@ static inline void sca_tx_done(port_t *port)
                        dev->stats.tx_bytes += readw(&desc->len);
                }
                writeb(0, &desc->stat); /* Free descriptor */
+               count++;
                port->txlast = (port->txlast + 1) % card->tx_ring_buffers;
        }
 
-       netif_wake_queue(dev);
+       if (count)
+               netif_wake_queue(dev);
        spin_unlock(&port->lock);
 }
 
index 8251946842e6186bddcd1cac303dbaea74664410..42ed923cdb1aad9479be7ed5f68a2b40c665ffcb 100644 (file)
@@ -1917,7 +1917,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                sc->bmisscount = 0;
        }
 
-       if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+       if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT) {
                u64 tsf = ath5k_hw_get_tsf64(ah);
                u32 tsftu = TSF_TO_TU(tsf);
                int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
@@ -1949,8 +1950,9 @@ ath5k_beacon_send(struct ath5k_softc *sc)
                /* NB: hw still stops DMA, so proceed */
        }
 
-       /* refresh the beacon for AP mode */
-       if (sc->opmode == NL80211_IFTYPE_AP)
+       /* refresh the beacon for AP or MESH mode */
+       if (sc->opmode == NL80211_IFTYPE_AP ||
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT)
                ath5k_beacon_update(sc->hw, vif);
 
        ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
@@ -2851,7 +2853,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
 
        /* Assign the vap/adhoc to a beacon xmit slot. */
        if ((avf->opmode == NL80211_IFTYPE_AP) ||
-           (avf->opmode == NL80211_IFTYPE_ADHOC)) {
+           (avf->opmode == NL80211_IFTYPE_ADHOC) ||
+           (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
                int slot;
 
                WARN_ON(list_empty(&sc->bcbuf));
@@ -2870,7 +2873,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
                sc->bslot[avf->bslot] = vif;
                if (avf->opmode == NL80211_IFTYPE_AP)
                        sc->num_ap_vifs++;
-               else
+               else if (avf->opmode == NL80211_IFTYPE_ADHOC)
                        sc->num_adhoc_vifs++;
        }
 
index c4182359bee46603cffc46e9781750087f2a5f0f..a7b82f0085d2e899da46f6139dcac2185b42f924 100644 (file)
@@ -55,6 +55,8 @@
 #define SUB_NUM_CTL_MODES_AT_5G_40 2    /* excluding HT40, EXT-OFDM */
 #define SUB_NUM_CTL_MODES_AT_2G_40 3    /* excluding HT40, EXT-OFDM, EXT-CCK */
 
+#define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
+
 static const struct ar9300_eeprom ar9300_default = {
        .eepromVersion = 2,
        .templateVersion = 2,
@@ -290,20 +292,21 @@ static const struct ar9300_eeprom ar9300_default = {
                }
         },
        .ctlPowerData_2G = {
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
+                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
-                { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
-                { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
-                { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+                { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
         },
        .modalHeader5G = {
                /* 4 idle,t1,t2,b (4 bits per setting) */
@@ -568,56 +571,56 @@ static const struct ar9300_eeprom ar9300_default = {
        .ctlPowerData_5G = {
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 0}, {60, 1}, {60, 0}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
+                               CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
                        }
                },
                {
                        {
-                               {60, 0}, {60, 1}, {60, 1}, {60, 0},
-                               {60, 1}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
-                               {60, 0}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+                               CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 0}, {60, 0}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 1},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 1}, {60, 0}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 1}, {60, 0},
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
                        }
                },
                {
                        {
-                               {60, 1}, {60, 0}, {60, 1}, {60, 1},
-                               {60, 1}, {60, 1}, {60, 0}, {60, 1},
+                               CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+                               CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
                        }
                },
         }
@@ -1827,9 +1830,9 @@ static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
        struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
 
        if (is2GHz)
-               return ctl_2g[idx].ctlEdges[edge].tPower;
+               return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]);
        else
-               return ctl_5g[idx].ctlEdges[edge].tPower;
+               return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]);
 }
 
 static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
@@ -1847,12 +1850,12 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
 
        if (is2GHz) {
                if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
-                   ctl_2g[idx].ctlEdges[edge - 1].flag)
-                       return ctl_2g[idx].ctlEdges[edge - 1].tPower;
+                   CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]);
        } else {
                if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
-                   ctl_5g[idx].ctlEdges[edge - 1].flag)
-                       return ctl_5g[idx].ctlEdges[edge - 1].tPower;
+                   CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1]))
+                       return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
        }
 
        return AR9300_MAX_RATE_POWER;
index 3c533bb983c72859c9fbea4563070f387747506e..655b3033396c7f89ce1585479afb918102f993ae 100644 (file)
@@ -261,17 +261,12 @@ struct cal_tgt_pow_ht {
        u8 tPow2x[14];
 } __packed;
 
-struct cal_ctl_edge_pwr {
-       u8 tPower:6,
-          flag:2;
-} __packed;
-
 struct cal_ctl_data_2g {
-       struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G];
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_2G];
 } __packed;
 
 struct cal_ctl_data_5g {
-       struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G];
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
 } __packed;
 
 struct ar9300_eeprom {
index 170d44a35ccbd2ca06886be2be2ed8c1cd5dcf25..0963071e8f908c15ebec8131c84b792d931e56d9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <linux/leds.h>
 #include <linux/completion.h>
+#include <linux/pm_qos_params.h>
 
 #include "debug.h"
 #include "common.h"
@@ -328,7 +329,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 int ath_tx_setup(struct ath_softc *sc, int haltype);
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 void ath_draintxq(struct ath_softc *sc,
                     struct ath_txq *txq, bool retry_tx);
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
@@ -646,6 +647,8 @@ struct ath_softc {
        struct ath_descdma txsdma;
 
        struct ath_ant_comb ant_comb;
+
+       struct pm_qos_request_list pm_qos_req;
 };
 
 struct ath_wiphy {
@@ -675,7 +678,6 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 }
 
 extern struct ieee80211_ops ath9k_ops;
-extern struct pm_qos_request_list ath9k_pm_qos_req;
 extern int modparam_nohwcrypt;
 extern int led_blink;
 
index 1266333f586d8f574cf8fcda7086f036f3d56403..2bbf94d0191edb0ddc84084a37b07172203f2485 100644 (file)
@@ -240,16 +240,16 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
        for (i = 0; (i < num_band_edges) &&
                     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
                if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
-                       twiceMaxEdgePower = pRdEdgesPower[i].tPower;
+                       twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
                        break;
                } else if ((i > 0) &&
                           (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
                                                      is2GHz))) {
                        if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
                                               is2GHz) < freq &&
-                           pRdEdgesPower[i - 1].flag) {
+                           CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
                                twiceMaxEdgePower =
-                                       pRdEdgesPower[i - 1].tPower;
+                                       CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
                        }
                        break;
                }
index dacb45e1b9063b620736475b6116975fcb60cf4d..dd59f09441a3cdf00cbc805a36e4734d58a04253 100644 (file)
 
 #define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1)
 
+#define CTL_EDGE_TPOWER(_ctl) ((_ctl) & 0x3f)
+#define CTL_EDGE_FLAGS(_ctl) (((_ctl) >> 6) & 0x03)
+
+#define LNA_CTL_BUF_MODE       BIT(0)
+#define LNA_CTL_ISEL_LO                BIT(1)
+#define LNA_CTL_ISEL_HI                BIT(2)
+#define LNA_CTL_BUF_IN         BIT(3)
+#define LNA_CTL_FEM_BAND       BIT(4)
+#define LNA_CTL_LOCAL_BIAS     BIT(5)
+#define LNA_CTL_FORCE_XPA      BIT(6)
+#define LNA_CTL_USE_ANT1       BIT(7)
+
 enum eeprom_param {
        EEP_NFTHRESH_5,
        EEP_NFTHRESH_2,
@@ -378,10 +390,7 @@ struct modal_eep_header {
        u8 xatten2Margin[AR5416_MAX_CHAINS];
        u8 ob_ch1;
        u8 db_ch1;
-       u8 useAnt1:1,
-           force_xpaon:1,
-           local_bias:1,
-           femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
+       u8 lna_ctl;
        u8 miscBits;
        u16 xpaBiasLvlFreq[3];
        u8 futureModal[6];
@@ -535,18 +544,10 @@ struct cal_target_power_ht {
        u8 tPow2x[8];
 } __packed;
 
-
-#ifdef __BIG_ENDIAN_BITFIELD
-struct cal_ctl_edges {
-       u8 bChannel;
-       u8 flag:2, tPower:6;
-} __packed;
-#else
 struct cal_ctl_edges {
        u8 bChannel;
-       u8 tPower:6, flag:2;
+       u8 ctl;
 } __packed;
-#endif
 
 struct cal_data_op_loop_ar9287 {
        u8 pwrPdg[2][5];
index 76b4d65472dd2b37dbf98ff69b57646e53443c61..a3ccb1b9638d7b8b44f32ba651d519d042b806ec 100644 (file)
@@ -451,9 +451,10 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
                ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
                                          AR_AN_TOP2_LOCALBIAS,
                                          AR_AN_TOP2_LOCALBIAS_S,
-                                         pModal->local_bias);
+                                         !!(pModal->lna_ctl &
+                                            LNA_CTL_LOCAL_BIAS));
                REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
-                             pModal->force_xpaon);
+                             !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));
        }
 
        REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
@@ -1062,15 +1063,19 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
        case 1:
                break;
        case 2:
-               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        case 3:
-               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
+                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+               else
+                       scaledPower = 0;
                break;
        }
 
-       scaledPower = max((u16)0, scaledPower);
-
        if (IS_CHAN_2GHZ(chan)) {
                numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
                        SUB_NUM_CTL_MODES_AT_2G_40;
@@ -1428,9 +1433,9 @@ static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
 
        num_ant_config = 1;
 
-       if (pBase->version >= 0x0E0D)
-               if (pModal->useAnt1)
-                       num_ant_config += 1;
+       if (pBase->version >= 0x0E0D &&
+           (pModal->lna_ctl & LNA_CTL_USE_ANT1))
+               num_ant_config += 1;
 
        return num_ant_config;
 }
index dfb6560dab9205c7502cc0a546c3549635d696f2..0de3c3d3c245c2ad5f71f0a419a7ba4fab96e60c 100644 (file)
@@ -1024,6 +1024,13 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface,
        struct hif_device_usb *hif_dev =
                (struct hif_device_usb *) usb_get_intfdata(interface);
 
+       /*
+        * The device has to be set to FULLSLEEP mode in case no
+        * interface is up.
+        */
+       if (!(hif_dev->flags & HIF_USB_START))
+               ath9k_htc_suspend(hif_dev->htc_handle);
+
        ath9k_hif_usb_dealloc_urbs(hif_dev);
 
        return 0;
index 75ecf6a30d25c6ac68d346c5ac862a0255ba4be1..c3b561daa6c1035a68f4b27da92914ba4e601399 100644 (file)
@@ -455,6 +455,8 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);
 void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
 void ath9k_ps_work(struct work_struct *work);
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
 void ath9k_init_leds(struct ath9k_htc_priv *priv);
@@ -464,6 +466,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
                           u16 devid, char *product);
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
 #ifdef CONFIG_PM
+void ath9k_htc_suspend(struct htc_target *htc_handle);
 int ath9k_htc_resume(struct htc_target *htc_handle);
 #endif
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
index 7c8a38d04561c26754147bea9e447724a9e8eb42..8776f49ffd41bf2a40f080798fe6c5173b80c9b4 100644 (file)
@@ -891,6 +891,12 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
 }
 
 #ifdef CONFIG_PM
+
+void ath9k_htc_suspend(struct htc_target *htc_handle)
+{
+       ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
+}
+
 int ath9k_htc_resume(struct htc_target *htc_handle)
 {
        int ret;
index 9a3be8da755d2f7181ada323e5ec9054b58a0a9e..51977caca47fd6d456e521cff4511e1079f2e09a 100644 (file)
@@ -63,8 +63,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
        return mode;
 }
 
-static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
-                              enum ath9k_power_mode mode)
+bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
+                       enum ath9k_power_mode mode)
 {
        bool ret;
 
index 6ebc68bca91f0a999614572b38f69452df49645d..c7fbe25cc12827cf29f68729fe636b07ef75ebfa 100644 (file)
@@ -2044,7 +2044,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
                val = REG_READ(ah, AR7010_GPIO_IN);
                return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
        } else if (AR_SREV_9300_20_OR_LATER(ah))
-               return MS_REG_READ(AR9300, gpio) != 0;
+               return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) &
+                       AR_GPIO_BIT(gpio)) != 0;
        else if (AR_SREV_9271(ah))
                return MS_REG_READ(AR9271, gpio) != 0;
        else if (AR_SREV_9287_11_OR_LATER(ah))
index 92bc5c5f48768ac42ca4b1bd02690d9d38ebed80..14b8ab386daff8823bcc3301fa52d467ce6cb01b 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/pm_qos_params.h>
 
 #include "ath9k.h"
 
@@ -180,8 +179,6 @@ static const struct ath_ops ath9k_common_ops = {
        .write = ath9k_iowrite32,
 };
 
-struct pm_qos_request_list ath9k_pm_qos_req;
-
 /**************************/
 /*     Initialization     */
 /**************************/
@@ -664,6 +661,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
        hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_P2P_GO) |
+               BIT(NL80211_IFTYPE_P2P_CLIENT) |
                BIT(NL80211_IFTYPE_AP) |
                BIT(NL80211_IFTYPE_WDS) |
                BIT(NL80211_IFTYPE_STATION) |
@@ -759,7 +758,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
        ath_init_leds(sc);
        ath_start_rfkill_poll(sc);
 
-       pm_qos_add_request(&ath9k_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
+       pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
                           PM_QOS_DEFAULT_VALUE);
 
        return 0;
@@ -830,7 +829,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
        }
 
        ieee80211_unregister_hw(hw);
-       pm_qos_remove_request(&ath9k_pm_qos_req);
+       pm_qos_remove_request(&sc->pm_qos_req);
        ath_rx_cleanup(sc);
        ath_tx_cleanup(sc);
        ath9k_deinit_softc(sc);
index 8c13479b17cd9d418f7d7f496b01dbf7445ba202..c996963ab33927c027f3fb019200261c0ac07d18 100644 (file)
@@ -703,8 +703,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
                        rs->rs_phyerr = phyerr;
                } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
-               else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
-                        rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
+               else if (ads.ds_rxstatus8 & AR_MichaelErr)
                        rs->rs_status |= ATH9K_RXERR_MIC;
                else if (ads.ds_rxstatus8 & AR_KeyMiss)
                        rs->rs_status |= ATH9K_RXERR_DECRYPT;
index 25d3ef4c338e1eb45800b45fec112fc064c095af..c0c3464d3a861162e1142a0e2931a73aedae1fab 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/nl80211.h>
-#include <linux/pm_qos_params.h>
 #include "ath9k.h"
 #include "btcoex.h"
 
@@ -245,11 +244,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
         * the relevant bits of the h/w.
         */
        ath9k_hw_set_interrupts(ah, 0);
-       ath_drain_all_txq(sc, false);
+       stopped = ath_drain_all_txq(sc, false);
 
        spin_lock_bh(&sc->rx.pcu_lock);
 
-       stopped = ath_stoprecv(sc);
+       if (!ath_stoprecv(sc))
+               stopped = false;
 
        /* XXX: do not flush receive queue here. We don't want
         * to flush data frames already in queue because of
@@ -1244,7 +1244,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
                        ath9k_btcoex_timer_resume(sc);
        }
 
-       pm_qos_update_request(&ath9k_pm_qos_req, 55);
+       pm_qos_update_request(&sc->pm_qos_req, 55);
 
 mutex_unlock:
        mutex_unlock(&sc->mutex);
@@ -1423,7 +1423,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
        sc->sc_flags |= SC_OP_INVALID;
 
-       pm_qos_update_request(&ath9k_pm_qos_req, PM_QOS_DEFAULT_VALUE);
+       pm_qos_update_request(&sc->pm_qos_req, PM_QOS_DEFAULT_VALUE);
 
        mutex_unlock(&sc->mutex);
 
@@ -1520,7 +1520,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
-       int i;
 
        ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
@@ -1534,21 +1533,24 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
            (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
+               /* Disable SWBA interrupt */
+               sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
                ath9k_ps_wakeup(sc);
+               ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
                ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
                ath9k_ps_restore(sc);
+               tasklet_kill(&sc->bcon_tasklet);
        }
 
        ath_beacon_return(sc, avp);
        sc->sc_flags &= ~SC_OP_BEACONS;
 
-       for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
-               if (sc->beacon.bslot[i] == vif) {
-                       printk(KERN_DEBUG "%s: vif had allocated beacon "
-                              "slot\n", __func__);
-                       sc->beacon.bslot[i] = NULL;
-                       sc->beacon.bslot_aphy[i] = NULL;
-               }
+       if (sc->nbcnvifs) {
+               /* Re-enable SWBA interrupt */
+               sc->sc_ah->imask |= ATH9K_INT_SWBA;
+               ath9k_ps_wakeup(sc);
+               ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+               ath9k_ps_restore(sc);
        }
 
        sc->nvifs--;
index 1a62e351ec77c217598a46fae7bdbcc84c1c6050..fdc2ec52b42fcd5647df2c967598e94bcfc13c9a 100644 (file)
@@ -838,6 +838,10 @@ static bool ath9k_rx_accept(struct ath_common *common,
                            struct ath_rx_status *rx_stats,
                            bool *decrypt_error)
 {
+#define is_mc_or_valid_tkip_keyix ((is_mc ||                   \
+               (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
+               test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
+
        struct ath_hw *ah = common->ah;
        __le16 fc;
        u8 rx_status_len = ah->caps.rx_status_len;
@@ -879,15 +883,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
                if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
                        *decrypt_error = true;
                } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
+                       bool is_mc;
                        /*
                         * The MIC error bit is only valid if the frame
                         * is not a control frame or fragment, and it was
                         * decrypted using a valid TKIP key.
                         */
+                       is_mc = !!is_multicast_ether_addr(hdr->addr1);
+
                        if (!ieee80211_is_ctl(fc) &&
                            !ieee80211_has_morefrags(fc) &&
                            !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-                           test_bit(rx_stats->rs_keyix, common->tkip_keymap))
+                           is_mc_or_valid_tkip_keyix)
                                rxs->flag |= RX_FLAG_MMIC_ERROR;
                        else
                                rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
index dddf579aacf1c391dfb3e9e73675de1a781760da..2c6a22fbb0f0cf76fb5ac5cfd22b530402e9f693 100644 (file)
@@ -984,11 +984,13 @@ enum {
 #define AR9287_GPIO_IN_VAL_S                     11
 #define AR9271_GPIO_IN_VAL                       0xFFFF0000
 #define AR9271_GPIO_IN_VAL_S                     16
-#define AR9300_GPIO_IN_VAL                       0x0001FFFF
-#define AR9300_GPIO_IN_VAL_S                     0
 #define AR7010_GPIO_IN_VAL                       0x0000FFFF
 #define AR7010_GPIO_IN_VAL_S                     0
 
+#define AR_GPIO_IN                              0x404c
+#define AR9300_GPIO_IN_VAL                       0x0001FFFF
+#define AR9300_GPIO_IN_VAL_S                     0
+
 #define AR_GPIO_OE_OUT                           (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)
 #define AR_GPIO_OE_OUT_DRV                       0x3
 #define AR_GPIO_OE_OUT_DRV_NO                    0x0
index f2ade2402ce27709e1da385941b9adbaece96b1e..aff04789f794ee805bf50f1f13d28783f79851d3 100644 (file)
@@ -1120,7 +1120,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
        }
 }
 
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -1128,7 +1128,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
        int i, npend = 0;
 
        if (sc->sc_flags & SC_OP_INVALID)
-               return;
+               return true;
 
        /* Stop beacon queue */
        ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
@@ -1142,25 +1142,15 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
                }
        }
 
-       if (npend) {
-               int r;
-
-               ath_print(common, ATH_DBG_FATAL,
-                         "Failed to stop TX DMA. Resetting hardware!\n");
-
-               spin_lock_bh(&sc->sc_resetlock);
-               r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
-               if (r)
-                       ath_print(common, ATH_DBG_FATAL,
-                                 "Unable to reset hardware; reset status %d\n",
-                                 r);
-               spin_unlock_bh(&sc->sc_resetlock);
-       }
+       if (npend)
+               ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA!\n");
 
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i))
                        ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
        }
+
+       return !npend;
 }
 
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
index ae6c006bbc56c03bd76f0e1cc56c46a927db1db9..546b4e4ec5ea090aaf6ed0ce7b77ed024e3c8fd6 100644 (file)
@@ -291,7 +291,8 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
 
                if (SUPP(CARL9170FW_WLANTX_CAB)) {
                        ar->hw->wiphy->interface_modes |=
-                               BIT(NL80211_IFTYPE_AP);
+                               BIT(NL80211_IFTYPE_AP) |
+                               BIT(NL80211_IFTYPE_P2P_GO);
                }
        }
 
index a314c2c2bfbea433849dc60ae7f44f67c2785358..dc7b30b170d037de1dc9b38b058458a98f8efb43 100644 (file)
@@ -1631,7 +1631,8 @@ void *carl9170_alloc(size_t priv_size)
         * supports these modes. The code which will add the
         * additional interface_modes is in fw.c.
         */
-       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+                                    BIT(NL80211_IFTYPE_P2P_CLIENT);
 
        hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
                     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
index b575c865142d64f82f8e072518c0de44e46039cc..7e6506a77bbb625a28ad0e6b41f7984607fe5f80 100644 (file)
@@ -810,7 +810,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
 
        mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
                              AR9170_TX_MAC_BACKOFF);
-       mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &&
+       mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &
                               AR9170_TX_MAC_QOS);
 
        no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
index e5685dc317a80423a7acb6a68694bba4043d3897..b4de0ca10feb8f9ef18b826e00f82a240fb40e91 100644 (file)
@@ -1170,7 +1170,6 @@ static void if_sdio_remove(struct sdio_func *func)
        lbs_deb_sdio("call remove card\n");
        lbs_stop_card(card->priv);
        lbs_remove_card(card->priv);
-       card->priv->surpriseremoved = 1;
 
        flush_workqueue(card->workqueue);
        destroy_workqueue(card->workqueue);
index 79bcb4e5d2ca03c7ccb82621576296a6ea68b5d0..ecd4d04b2c3cea67aebd6d62c9446a3318a2840c 100644 (file)
@@ -1055,7 +1055,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
        lbs_stop_card(priv);
        lbs_remove_card(priv); /* will call free_netdev */
 
-       priv->surpriseremoved = 1;
        free_irq(spi->irq, card);
        if_spi_terminate_spi_thread(card);
        if (card->pdata->teardown)
index 46b88b118c992c12764084233f8633a62a01a629..fcd1bbfc632d527364b8f1fc91abd70ba3242225 100644 (file)
@@ -915,8 +915,6 @@ void lbs_remove_card(struct lbs_private *priv)
 
        lbs_free_adapter(priv);
        lbs_cfg_free(priv);
-
-       priv->dev = NULL;
        free_netdev(dev);
 
        lbs_deb_leave(LBS_DEB_MAIN);
index e8e2d0f4763db4f33e899ad712595d9af5173333..f3d396e7544b9d1d0f7848bc1cabb74bce75b8de 100644 (file)
@@ -1392,10 +1392,9 @@ static void orinoco_process_scan_results(struct work_struct *work)
                                orinoco_add_hostscan_results(priv, buf, len);
 
                        kfree(buf);
-               } else if (priv->scan_request) {
+               } else {
                        /* Either abort or complete the scan */
-                       cfg80211_scan_done(priv->scan_request, (len < 0));
-                       priv->scan_request = NULL;
+                       orinoco_scan_done(priv, (len < 0));
                }
 
                spin_lock_irqsave(&priv->scan_lock, flags);
@@ -1684,6 +1683,8 @@ static int __orinoco_down(struct orinoco_private *priv)
                hermes_write_regn(hw, EVACK, 0xffff);
        }
 
+       orinoco_scan_done(priv, true);
+
        /* firmware will have to reassociate */
        netif_carrier_off(dev);
        priv->last_linkstatus = 0xffff;
@@ -1762,10 +1763,7 @@ void orinoco_reset(struct work_struct *work)
        orinoco_unlock(priv, &flags);
 
        /* Scanning support: Notify scan cancellation */
-       if (priv->scan_request) {
-               cfg80211_scan_done(priv->scan_request, 1);
-               priv->scan_request = NULL;
-       }
+       orinoco_scan_done(priv, true);
 
        if (priv->hard_reset) {
                err = (*priv->hard_reset)(priv);
@@ -1813,6 +1811,12 @@ static int __orinoco_commit(struct orinoco_private *priv)
        struct net_device *dev = priv->ndev;
        int err = 0;
 
+       /* If we've called commit, we are reconfiguring or bringing the
+        * interface up. Maintaining countermeasures across this would
+        * be confusing, so note that we've disabled them. The port will
+        * be enabled later in orinoco_commit or __orinoco_up. */
+       priv->tkip_cm_active = 0;
+
        err = orinoco_hw_program_rids(priv);
 
        /* FIXME: what about netif_tx_lock */
index 71b3d68b9403a8c4c142b776179c1edef9328ebd..32954c4b243a9dc70bbb0fd350c6c79ff67875d3 100644 (file)
@@ -151,20 +151,20 @@ orinoco_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index 4300d9db7d8caab2d70442b7cbd37a9da69adef9..86cb54c842e745ffd7863457f23f45185440f556 100644 (file)
@@ -229,3 +229,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
                priv->scan_request = NULL;
        }
 }
+
+void orinoco_scan_done(struct orinoco_private *priv, bool abort)
+{
+       if (priv->scan_request) {
+               cfg80211_scan_done(priv->scan_request, abort);
+               priv->scan_request = NULL;
+       }
+}
index 2dc4e046dbdb61c5c19f33e14f6ae4fae381a8c9..27281fb0a6dc02f529b4ea1edf2fb29e2a6903be 100644 (file)
@@ -16,5 +16,6 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
 void orinoco_add_hostscan_results(struct orinoco_private *dev,
                                  unsigned char *buf,
                                  size_t len);
+void orinoco_scan_done(struct orinoco_private *priv, bool abort);
 
 #endif /* _ORINOCO_SCAN_H_ */
index fb859a5ad2eb8a5c2e02f349cf4002caac32fc49..db34c282e59b39340a9bf7c6c51f529bf020a1c0 100644 (file)
@@ -214,21 +214,21 @@ spectrum_cs_config(struct pcmcia_device *link)
                goto failed;
        }
 
-       ret = pcmcia_request_irq(link, orinoco_interrupt);
-       if (ret)
-               goto failed;
-
-       /* We initialize the hermes structure before completing PCMCIA
-        * configuration just in case the interrupt handler gets
-        * called. */
        mem = ioport_map(link->resource[0]->start,
                        resource_size(link->resource[0]));
        if (!mem)
                goto failed;
 
+       /* We initialize the hermes structure before completing PCMCIA
+        * configuration just in case the interrupt handler gets
+        * called. */
        hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
        hw->eeprom_pda = true;
 
+       ret = pcmcia_request_irq(link, orinoco_interrupt);
+       if (ret)
+               goto failed;
+
        ret = pcmcia_enable_device(link);
        if (ret)
                goto failed;
index 93505f93bf97711019e86bbe27f39f4f727bce01..e5afabee60d1834b898193479cf710c3bb3eed22 100644 (file)
@@ -911,10 +911,10 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
                 */
                if (param->value) {
                        priv->tkip_cm_active = 1;
-                       ret = hermes_enable_port(hw, 0);
+                       ret = hermes_disable_port(hw, 0);
                } else {
                        priv->tkip_cm_active = 0;
-                       ret = hermes_disable_port(hw, 0);
+                       ret = hermes_enable_port(hw, 0);
                }
                break;
 
index 458bb57914a32d57948ff425508f6b40ac2de7e1..cdbeec9f83ea256507c57762dda8a7f73e69983e 100644 (file)
@@ -66,8 +66,8 @@ struct netfront_cb {
 
 #define GRANT_INVALID_REF      0
 
-#define NET_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE)
-#define NET_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE)
+#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
+#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
 #define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
 
 struct netfront_info {
index c80a7a6e76980a67677d07bc7bd4f59f9e3635be..de886f3dfd3926c8cd9f1974926ff1689baf027f 100644 (file)
@@ -215,7 +215,8 @@ config PCMCIA_PXA2XX
        depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
                    || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
                    || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \
-                   || MACH_VPAC270 || MACH_BALLOON3)
+                   || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
+                   || MACH_COLIBRI320)
        select PCMCIA_SOC_COMMON
        help
          Say Y here to include support for the PXA2xx PCMCIA controller
index 8d9386a22eb3392ad0537e3d9491ab8f7e833763..9a44a90dcf7a36f069739dc14c999681ae8b50d0 100644 (file)
@@ -70,6 +70,8 @@ pxa2xx-obj-$(CONFIG_MACH_E740)                        += pxa2xx_e740.o
 pxa2xx-obj-$(CONFIG_MACH_STARGATE2)            += pxa2xx_stargate2.o
 pxa2xx-obj-$(CONFIG_MACH_VPAC270)              += pxa2xx_vpac270.o
 pxa2xx-obj-$(CONFIG_MACH_BALLOON3)             += pxa2xx_balloon3.o
+pxa2xx-obj-$(CONFIG_MACH_COLIBRI)              += pxa2xx_colibri.o
+pxa2xx-obj-$(CONFIG_MACH_COLIBRI320)           += pxa2xx_colibri.o
 
 obj-$(CONFIG_PCMCIA_PXA2XX)                    += pxa2xx_base.o $(pxa2xx-obj-y)
 
index dbbdd0063202d91f76b7cd8e053b747041ca55a8..453c54c97612833b341a1e9787d9a8d51c7ec223 100644 (file)
@@ -39,12 +39,10 @@ static struct pcmcia_irqs irqs[] = {
 static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
        uint16_t ver;
-       int ret;
-       static void __iomem *fpga_ver;
 
        ver = __raw_readw(BALLOON3_FPGA_VER);
-       if (ver > 0x0201)
-               pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. "
+       if (ver < 0x4f08)
+               pr_warn("The FPGA code, version 0x%04x, is too old. "
                        "PCMCIA/CF support might be broken in this version!",
                        ver);
 
@@ -97,8 +95,9 @@ static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
                                       const socket_state_t *state)
 {
-       __raw_writew((state->flags & SS_RESET) ? BALLOON3_CF_RESET : 0,
-                       BALLOON3_CF_CONTROL_REG);
+       __raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG |
+                       ((state->flags & SS_RESET) ?
+                       BALLOON3_FPGA_SETnCLR : 0));
        return 0;
 }
 
index ae07b4db8a6ec00def420e5af77bbcede2b90730..3755e7c8c715f5f9bebf60c5d9a7ff4a5e250f65 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 
 #include <mach/hardware.h>
+#include <mach/smemc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -116,37 +117,49 @@ static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,
 
 static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock )
 {
-       MCMEM(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+       uint32_t val;
+
+       val = ((pxa2xx_mcxx_setup(speed, clock)
                & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
                | ((pxa2xx_mcxx_asst(speed, clock)
                & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
                | ((pxa2xx_mcxx_hold(speed, clock)
                & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+       __raw_writel(val, MCMEM(sock));
+
        return 0;
 }
 
 static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock )
 {
-       MCIO(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+       uint32_t val;
+
+       val = ((pxa2xx_mcxx_setup(speed, clock)
                & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
                | ((pxa2xx_mcxx_asst(speed, clock)
                & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
                | ((pxa2xx_mcxx_hold(speed, clock)
                & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+       __raw_writel(val, MCIO(sock));
+
        return 0;
 }
 
 static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock )
 {
-       MCATT(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+       uint32_t val;
+
+       val = ((pxa2xx_mcxx_setup(speed, clock)
                & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
                | ((pxa2xx_mcxx_asst(speed, clock)
                & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
                | ((pxa2xx_mcxx_hold(speed, clock)
                & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+       __raw_writel(val, MCATT(sock));
+
        return 0;
 }
 
@@ -166,8 +179,8 @@ static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int cl
 
 static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
 {
-       unsigned int clk = get_memclk_frequency_10khz();
-       return pxa2xx_pcmcia_set_mcxx(skt, clk);
+       unsigned long clk = clk_get_rate(skt->clk);
+       return pxa2xx_pcmcia_set_mcxx(skt, clk / 10000);
 }
 
 #ifdef CONFIG_CPU_FREQ
@@ -205,19 +218,18 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
 static void pxa2xx_configure_sockets(struct device *dev)
 {
        struct pcmcia_low_level *ops = dev->platform_data;
-
        /*
         * We have at least one socket, so set MECR:CIT
         * (Card Is There)
         */
-       MECR |= MECR_CIT;
+       uint32_t mecr = MECR_CIT;
 
        /* Set MECR:NOS (Number Of Sockets) */
        if ((ops->first + ops->nr) > 1 ||
            machine_is_viper() || machine_is_arcom_zeus())
-               MECR |= MECR_NOS;
-       else
-               MECR &= ~MECR_NOS;
+               mecr |= MECR_NOS;
+
+       __raw_writel(mecr, MECR);
 }
 
 static const char *skt_names[] = {
@@ -270,24 +282,41 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
        struct pcmcia_low_level *ops;
        struct skt_dev_info *sinfo;
        struct soc_pcmcia_socket *skt;
+       struct clk *clk;
 
        ops = (struct pcmcia_low_level *)dev->dev.platform_data;
-       if (!ops)
+       if (!ops) {
+               ret = -ENODEV;
+               goto err0;
+       }
+
+       if (cpu_is_pxa320() && ops->nr > 1) {
+               dev_err(&dev->dev, "pxa320 supports only one pcmcia slot");
+               ret = -EINVAL;
+               goto err0;
+       }
+
+       clk = clk_get(&dev->dev, NULL);
+       if (!clk)
                return -ENODEV;
 
        pxa2xx_drv_pcmcia_ops(ops);
 
        sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
-       if (!sinfo)
+       if (!sinfo) {
+               clk_put(clk);
                return -ENOMEM;
+       }
 
        sinfo->nskt = ops->nr;
+       sinfo->clk = clk;
 
        /* Initialize processor specific parameters */
        for (i = 0; i < ops->nr; i++) {
                skt = &sinfo->skt[i];
 
                skt->nr = ops->first + i;
+               skt->clk = clk;
                skt->ops = ops;
                skt->socket.owner = ops->owner;
                skt->socket.dev.parent = &dev->dev;
@@ -295,18 +324,26 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
 
                ret = pxa2xx_drv_pcmcia_add_one(skt);
                if (ret)
-                       break;
+                       goto err1;
        }
 
        if (ret) {
                while (--i >= 0)
                        soc_pcmcia_remove_one(&sinfo->skt[i]);
                kfree(sinfo);
+               clk_put(clk);
        } else {
                pxa2xx_configure_sockets(&dev->dev);
                dev_set_drvdata(&dev->dev, sinfo);
        }
 
+       return 0;
+
+err1:
+       while (--i >= 0)
+               soc_pcmcia_remove_one(&sinfo->skt[i]);
+       kfree(sinfo);
+err0:
        return ret;
 }
 
@@ -320,6 +357,7 @@ static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
        for (i = 0; i < sinfo->nskt; i++)
                soc_pcmcia_remove_one(&sinfo->skt[i]);
 
+       clk_put(sinfo->clk);
        kfree(sinfo);
        return 0;
 }
diff --git a/drivers/pcmcia/pxa2xx_colibri.c b/drivers/pcmcia/pxa2xx_colibri.c
new file mode 100644 (file)
index 0000000..c3f7219
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_colibri.c
+ *
+ * Driver for Toradex Colibri PXA270 CF socket
+ *
+ * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+
+#include "soc_common.h"
+
+#define        COLIBRI270_RESET_GPIO   53
+#define        COLIBRI270_PPEN_GPIO    107
+#define        COLIBRI270_BVD1_GPIO    83
+#define        COLIBRI270_BVD2_GPIO    82
+#define        COLIBRI270_DETECT_GPIO  84
+#define        COLIBRI270_READY_GPIO   1
+
+#define        COLIBRI320_RESET_GPIO   77
+#define        COLIBRI320_PPEN_GPIO    57
+#define        COLIBRI320_BVD1_GPIO    53
+#define        COLIBRI320_BVD2_GPIO    79
+#define        COLIBRI320_DETECT_GPIO  81
+#define        COLIBRI320_READY_GPIO   29
+
+static struct {
+       int     reset_gpio;
+       int     ppen_gpio;
+       int     bvd1_gpio;
+       int     bvd2_gpio;
+       int     detect_gpio;
+       int     ready_gpio;
+} colibri_pcmcia_gpio;
+
+static struct pcmcia_irqs colibri_irqs[] = {
+       {
+               .sock = 0,
+               .str  = "PCMCIA CD"
+       },
+};
+
+static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+       int ret;
+
+       ret = gpio_request(colibri_pcmcia_gpio.detect_gpio, "DETECT");
+       if (ret)
+               goto err1;
+       ret = gpio_direction_input(colibri_pcmcia_gpio.detect_gpio);
+       if (ret)
+               goto err2;
+
+       ret = gpio_request(colibri_pcmcia_gpio.ready_gpio, "READY");
+       if (ret)
+               goto err2;
+       ret = gpio_direction_input(colibri_pcmcia_gpio.ready_gpio);
+       if (ret)
+               goto err3;
+
+       ret = gpio_request(colibri_pcmcia_gpio.bvd1_gpio, "BVD1");
+       if (ret)
+               goto err3;
+       ret = gpio_direction_input(colibri_pcmcia_gpio.bvd1_gpio);
+       if (ret)
+               goto err4;
+
+       ret = gpio_request(colibri_pcmcia_gpio.bvd2_gpio, "BVD2");
+       if (ret)
+               goto err4;
+       ret = gpio_direction_input(colibri_pcmcia_gpio.bvd2_gpio);
+       if (ret)
+               goto err5;
+
+       ret = gpio_request(colibri_pcmcia_gpio.ppen_gpio, "PPEN");
+       if (ret)
+               goto err5;
+       ret = gpio_direction_output(colibri_pcmcia_gpio.ppen_gpio, 0);
+       if (ret)
+               goto err6;
+
+       ret = gpio_request(colibri_pcmcia_gpio.reset_gpio, "RESET");
+       if (ret)
+               goto err6;
+       ret = gpio_direction_output(colibri_pcmcia_gpio.reset_gpio, 1);
+       if (ret)
+               goto err7;
+
+       colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpio.detect_gpio);
+       skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpio.ready_gpio);
+
+       return soc_pcmcia_request_irqs(skt, colibri_irqs,
+                                       ARRAY_SIZE(colibri_irqs));
+
+err7:
+       gpio_free(colibri_pcmcia_gpio.detect_gpio);
+err6:
+       gpio_free(colibri_pcmcia_gpio.ready_gpio);
+err5:
+       gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
+err4:
+       gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
+err3:
+       gpio_free(colibri_pcmcia_gpio.reset_gpio);
+err2:
+       gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+err1:
+       return ret;
+}
+
+static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+       gpio_free(colibri_pcmcia_gpio.detect_gpio);
+       gpio_free(colibri_pcmcia_gpio.ready_gpio);
+       gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
+       gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
+       gpio_free(colibri_pcmcia_gpio.reset_gpio);
+       gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+}
+
+static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+                                       struct pcmcia_state *state)
+{
+
+       state->detect = !!gpio_get_value(colibri_pcmcia_gpio.detect_gpio);
+       state->ready  = !!gpio_get_value(colibri_pcmcia_gpio.ready_gpio);
+       state->bvd1   = !!gpio_get_value(colibri_pcmcia_gpio.bvd1_gpio);
+       state->bvd2   = !!gpio_get_value(colibri_pcmcia_gpio.bvd2_gpio);
+       state->wrprot = 0;
+       state->vs_3v  = 1;
+       state->vs_Xv  = 0;
+}
+
+static int
+colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+                               const socket_state_t *state)
+{
+       gpio_set_value(colibri_pcmcia_gpio.ppen_gpio,
+                       !(state->Vcc == 33 && state->Vpp < 50));
+       gpio_set_value(colibri_pcmcia_gpio.reset_gpio, state->flags & SS_RESET);
+       return 0;
+}
+
+static void colibri_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void colibri_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level colibri_pcmcia_ops = {
+       .owner                  = THIS_MODULE,
+
+       .first                  = 0,
+       .nr                     = 1,
+
+       .hw_init                = colibri_pcmcia_hw_init,
+       .hw_shutdown            = colibri_pcmcia_hw_shutdown,
+
+       .socket_state           = colibri_pcmcia_socket_state,
+       .configure_socket       = colibri_pcmcia_configure_socket,
+
+       .socket_init            = colibri_pcmcia_socket_init,
+       .socket_suspend         = colibri_pcmcia_socket_suspend,
+};
+
+static struct platform_device *colibri_pcmcia_device;
+
+static int __init colibri_pcmcia_init(void)
+{
+       int ret;
+
+       colibri_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+       if (!colibri_pcmcia_device)
+               return -ENOMEM;
+
+       /* Colibri PXA270 */
+       if (machine_is_colibri()) {
+               colibri_pcmcia_gpio.reset_gpio  = COLIBRI270_RESET_GPIO;
+               colibri_pcmcia_gpio.ppen_gpio   = COLIBRI270_PPEN_GPIO;
+               colibri_pcmcia_gpio.bvd1_gpio   = COLIBRI270_BVD1_GPIO;
+               colibri_pcmcia_gpio.bvd2_gpio   = COLIBRI270_BVD2_GPIO;
+               colibri_pcmcia_gpio.detect_gpio = COLIBRI270_DETECT_GPIO;
+               colibri_pcmcia_gpio.ready_gpio  = COLIBRI270_READY_GPIO;
+       /* Colibri PXA320 */
+       } else if (machine_is_colibri320()) {
+               colibri_pcmcia_gpio.reset_gpio  = COLIBRI320_RESET_GPIO;
+               colibri_pcmcia_gpio.ppen_gpio   = COLIBRI320_PPEN_GPIO;
+               colibri_pcmcia_gpio.bvd1_gpio   = COLIBRI320_BVD1_GPIO;
+               colibri_pcmcia_gpio.bvd2_gpio   = COLIBRI320_BVD2_GPIO;
+               colibri_pcmcia_gpio.detect_gpio = COLIBRI320_DETECT_GPIO;
+               colibri_pcmcia_gpio.ready_gpio  = COLIBRI320_READY_GPIO;
+       }
+
+       ret = platform_device_add_data(colibri_pcmcia_device,
+               &colibri_pcmcia_ops, sizeof(colibri_pcmcia_ops));
+
+       if (!ret)
+               ret = platform_device_add(colibri_pcmcia_device);
+
+       if (ret)
+               platform_device_put(colibri_pcmcia_device);
+
+       return ret;
+}
+
+static void __exit colibri_pcmcia_exit(void)
+{
+       platform_device_unregister(colibri_pcmcia_device);
+}
+
+module_init(colibri_pcmcia_init);
+module_exit(colibri_pcmcia_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PCMCIA support for Toradex Colibri PXA270/PXA320");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_LICENSE("GPL");
index bbcd5385a221ae40d5dc0ffb0d21cbf1a09de602..9daa73615c8bba3914f1a2fbf44fbfaa09e33b47 100644 (file)
@@ -10,6 +10,7 @@
 #define _ASM_ARCH_PCMCIA
 
 /* include the world */
+#include <linux/clk.h>
 #include <linux/cpufreq.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
@@ -29,6 +30,7 @@ struct soc_pcmcia_socket {
         * Info from low level handler
         */
        unsigned int            nr;
+       struct clk              *clk;
 
        /*
         * Core PCMCIA state
@@ -56,6 +58,7 @@ struct soc_pcmcia_socket {
 
 struct skt_dev_info {
        int nskt;
+       struct clk *clk;
        struct soc_pcmcia_socket skt[0];
 };
 
index 2d73dfcecdbb4e2098e3d881a6a091a9e8ca5e62..57313f4658bc55a00a5a7d36fbb86450f8144def 100644 (file)
@@ -180,7 +180,7 @@ struct pnp_protocol pnpacpi_protocol = {
 };
 EXPORT_SYMBOL(pnpacpi_protocol);
 
-static char *pnpacpi_get_id(struct acpi_device *device)
+static char *__init pnpacpi_get_id(struct acpi_device *device)
 {
        struct acpi_hardware_id *id;
 
index 51237fbb1bbb7e15f952296a9ffcb9f668418fc9..6d20b0454a1d7284c7728e3ec0c85d7d8e22f452 100644 (file)
@@ -231,8 +231,7 @@ static int tps6586x_dvm_voltages[] = {
 };
 
 #define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits,       \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)    \
-{                                                                      \
+                          ereg0, ebit0, ereg1, ebit1)                  \
        .desc   = {                                                     \
                .name   = "REG-" #_id,                                  \
                .ops    = &tps6586x_regulator_##_ops,                   \
@@ -248,18 +247,26 @@ static int tps6586x_dvm_voltages[] = {
        .enable_bit[0]  = (ebit0),                                      \
        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
        .enable_bit[1]  = (ebit1),                                      \
-       .voltages       = tps6586x_##vdata##_voltages,                  \
-}
+       .voltages       = tps6586x_##vdata##_voltages,
+
+#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                     \
+       .go_reg = TPS6586X_##goreg,                                     \
+       .go_bit = (gobit),
 
 #define TPS6586X_LDO(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1)                        \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, 0, 0)
+                          ereg0, ebit0, ereg1, ebit1)                  \
+}
 
 #define TPS6586X_DVM(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)
+                          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),
@@ -267,11 +274,11 @@ static struct tps6586x_regulator tps6586x_regulator[] = {
        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, SUPPLYV1, 5, 3, ENC, 6, END, 6),
+       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, 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, 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),
@@ -290,6 +297,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        uint8_t val1, val2;
        int ret;
 
+       if (ri->enable_reg[0] == ri->enable_reg[1] &&
+           ri->enable_bit[0] == ri->enable_bit[1])
+                       return 0;
+
        ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
        if (ret)
                return ret;
@@ -298,14 +309,14 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        if (ret)
                return ret;
 
-       if (!(val2 & ri->enable_bit[1]))
+       if (!(val2 & (1 << ri->enable_bit[1])))
                return 0;
 
        /*
         * The regulator is on, but it's enabled with the bit we don't
         * want to use, so we switch the enable bits
         */
-       if (!(val1 & ri->enable_bit[0])) {
+       if (!(val1 & (1 << ri->enable_bit[0]))) {
                ret = tps6586x_set_bits(parent, ri->enable_reg[0],
                                        1 << ri->enable_bit[0]);
                if (ret)
index d37c7331f244f1463c154a05ec9649306fe0c358..0bcd5806bd9a616df1f919f77c7e6a741e44533e 100644 (file)
@@ -156,6 +156,8 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
                if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
                      a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
                        return 0;
+               if (p_status & ZFCP_STATUS_COMMON_NOESC)
+                       return need;
                if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED))
                        need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
                /* fall through */
@@ -188,6 +190,9 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
                                &zfcp_sdev->status);
                erp_action = &zfcp_sdev->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
+               erp_action->port = port;
+               erp_action->sdev = sdev;
                if (!(atomic_read(&zfcp_sdev->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -200,6 +205,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_port(port);
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
                erp_action = &port->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
+               erp_action->port = port;
                if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
                break;
@@ -209,6 +216,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_adapter(adapter);
                atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
                erp_action = &adapter->erp_action;
+               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -218,10 +226,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                return NULL;
        }
 
-       memset(erp_action, 0, sizeof(struct zfcp_erp_action));
        erp_action->adapter = adapter;
-       erp_action->port = port;
-       erp_action->sdev = sdev;
        erp_action->action = need;
        erp_action->status = act_status;
 
index be0317457147fc4a891f4b0be67c8116b98526b1..2eb7dd56ab800af62da15d6a4cde42f2caf6177f 100644 (file)
@@ -851,7 +851,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
 
        zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
-       req->data = zfcp_sdev;
+       req->data = sdev;
        req->handler = zfcp_fsf_abort_fcp_command_handler;
        req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
        req->qtcb->header.port_handle = zfcp_sdev->port->handle;
@@ -2069,8 +2069,6 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
        struct fcp_resp_with_ext *fcp_rsp;
        unsigned long flags;
 
-       zfcp_fsf_fcp_handler_common(req);
-
        read_lock_irqsave(&req->adapter->abort_lock, flags);
 
        scpnt = req->data;
@@ -2079,6 +2077,8 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
                return;
        }
 
+       zfcp_fsf_fcp_handler_common(req);
+
        if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
                set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
                goto skip_fsfstatus;
@@ -2170,12 +2170,13 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
        struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        struct zfcp_qdio *qdio = adapter->qdio;
        struct fsf_qtcb_bottom_io *io;
+       unsigned long flags;
 
        if (unlikely(!(atomic_read(&zfcp_sdev->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                return -EBUSY;
 
-       spin_lock(&qdio->req_q_lock);
+       spin_lock_irqsave(&qdio->req_q_lock, flags);
        if (atomic_read(&qdio->req_q_free) <= 0) {
                atomic_inc(&qdio->req_q_full);
                goto out;
@@ -2239,7 +2240,7 @@ failed_scsi_cmnd:
        zfcp_fsf_req_free(req);
        scsi_cmnd->host_scribble = NULL;
 out:
-       spin_unlock(&qdio->req_q_lock);
+       spin_unlock_irqrestore(&qdio->req_q_lock, flags);
        return retval;
 }
 
index 6bd2dbc4c31606d5019fb1e76d92ef88583a2140..63529ed801eb3e4a37c768f1b55851863b60e9cb 100644 (file)
@@ -76,8 +76,8 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
        scpnt->scsi_done(scpnt);
 }
 
-static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
-                                 void (*done) (struct scsi_cmnd *))
+static
+int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
 {
        struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
        struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
@@ -87,7 +87,6 @@ static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
        /* reset the status for this request */
        scpnt->result = 0;
        scpnt->host_scribble = NULL;
-       scpnt->scsi_done = done;
 
        scsi_result = fc_remote_port_chkready(rport);
        if (unlikely(scsi_result)) {
@@ -127,8 +126,6 @@ static int zfcp_scsi_queuecommand_lck(struct scsi_cmnd *scpnt,
        return ret;
 }
 
-static DEF_SCSI_QCMD(zfcp_scsi_queuecommand)
-
 static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
 {
        struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
index b2fb2b2a6e700e86d7de265503b70cb48830d994..a6dea08664fc638c611260cbdd067978fb8b8092 100644 (file)
@@ -90,11 +90,7 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3252},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3253},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3254},
-#define PCI_DEVICE_ID_HP_CISSF 0x333f
-       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x333F},
-       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
-       {PCI_VENDOR_ID_COMPAQ,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
+       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,      PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
        {0,}
 };
@@ -113,8 +109,6 @@ static struct board_type products[] = {
        {0x3249103C, "Smart Array P812", &SA5_access},
        {0x324a103C, "Smart Array P712m", &SA5_access},
        {0x324b103C, "Smart Array P711m", &SA5_access},
-       {0x3233103C, "StorageWorks P1210m", &SA5_access},
-       {0x333F103C, "StorageWorks P1210m", &SA5_access},
        {0x3250103C, "Smart Array", &SA5_access},
        {0x3250113C, "Smart Array", &SA5_access},
        {0x3250123C, "Smart Array", &SA5_access},
index 0433ea6f27c9c2db97c464ca238afce39ebd0fcb..b37c8a3c1bb0de6d1b64fdf9ea3cbb8357f13805 100644 (file)
@@ -951,8 +951,8 @@ static int _osd_req_finalize_cdb_cont(struct osd_request *or, const u8 *cap_key)
        /* create a bio for continuation segment */
        bio = bio_map_kern(req_q, or->cdb_cont.buff, or->cdb_cont.total_bytes,
                           GFP_KERNEL);
-       if (unlikely(!bio))
-               return -ENOMEM;
+       if (IS_ERR(bio))
+               return PTR_ERR(bio);
 
        bio->bi_rw |= REQ_WRITE;
 
index 5e76a624cb08a843d194e7102900dfac77c2aae4..300d59f389da76175ac4720fc2d9a69b0a16b163 100644 (file)
@@ -62,6 +62,7 @@
 static unsigned int pmcraid_debug_log;
 static unsigned int pmcraid_disable_aen;
 static unsigned int pmcraid_log_level = IOASC_LOG_LEVEL_MUST;
+static unsigned int pmcraid_enable_msix;
 
 /*
  * Data structures to support multiple adapters by the LLD.
@@ -4691,7 +4692,8 @@ pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance)
        int rc;
        struct pci_dev *pdev = pinstance->pdev;
 
-       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+       if ((pmcraid_enable_msix) &&
+               (pci_find_capability(pdev, PCI_CAP_ID_MSIX))) {
                int num_hrrq = PMCRAID_NUM_MSIX_VECTORS;
                struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS];
                int i;
index 1134279604e805780f84607c523bbdd647685f24..4db210d93947275efd67e493549d75162fdf21e1 100644 (file)
@@ -42,7 +42,7 @@
  */
 #define PMCRAID_DRIVER_NAME            "PMC MaxRAID"
 #define PMCRAID_DEVFILE                        "pmcsas"
-#define PMCRAID_DRIVER_VERSION         "2.0.3"
+#define PMCRAID_DRIVER_VERSION         "1.0.3"
 #define PMCRAID_DRIVER_DATE            __DATE__
 
 #define PMCRAID_FW_VERSION_1           0x002
@@ -333,11 +333,9 @@ struct pmcraid_config_table_entry {
        __u8  lun[PMCRAID_LUN_LEN];
 } __attribute__((packed, aligned(4)));
 
-/* extended configuration table sizes are of 64 bytes in size */
-#define PMCRAID_CFGTE_EXT_SIZE 32
+/* extended configuration table sizes are also of 32 bytes in size */
 struct pmcraid_config_table_entry_ext {
        struct pmcraid_config_table_entry cfgte;
-       __u8  cfgte_ext[PMCRAID_CFGTE_EXT_SIZE];
 };
 
 /* resource types (config_table_entry.resource_type values) */
index 3a22effced5fa1a94996582b9fd13ccf151d8861..9ce539d4557e2a18d495ec2a31366cf5ebccc4aa 100644 (file)
@@ -2409,7 +2409,6 @@ struct qla_hw_data {
                uint32_t        enable_target_reset     :1;
                uint32_t        enable_lip_full_login   :1;
                uint32_t        enable_led_scheme       :1;
-               uint32_t        inta_enabled            :1;
                uint32_t        msi_enabled             :1;
                uint32_t        msix_enabled            :1;
                uint32_t        disable_serdes          :1;
index 5f94430b42f03974fda76e9f1f969cedbf3e9047..4c1ba6263eb32c1a228f2044b314c4e902f1c677 100644 (file)
@@ -1061,6 +1061,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
                fcp_cmnd->additional_cdb_len |= 2;
 
        int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun);
+       host_to_fcp_swap((uint8_t *)&fcp_cmnd->lun, sizeof(fcp_cmnd->lun));
        memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
        cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len);
        cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
index 1f06ddd9bdd10cdbe6526de1deaaab194a19118e..7f77898486a9014f1e4848e77648f78c5dce1c75 100644 (file)
@@ -2491,14 +2491,15 @@ skip_msix:
 skip_msi:
 
        ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
-           IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
+           ha->flags.msi_enabled ? 0 : IRQF_SHARED,
+           QLA2XXX_DRIVER_NAME, rsp);
        if (ret) {
                qla_printk(KERN_WARNING, ha,
                    "Failed to reserve interrupt %d already in use.\n",
                    ha->pdev->irq);
                goto fail;
        }
-       ha->flags.inta_enabled = 1;
+
 clear_risc_ints:
 
        /*
index 8d9edfb39803ff26809743ef8cf5e0b22abd305b..ae2acacc00036558c5ddb0e246e8b691097c80ca 100644 (file)
@@ -2749,6 +2749,7 @@ sufficient_dsds:
                        goto queuing_error_fcp_cmnd;
 
                int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
+               host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
                /* build FCP_CMND IU */
                memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
index 1644eabaafeb58cb3130dccdb97b489bcd0c708e..2c0876c81a3f6e5793d504b825146b6de7c2ae81 100644 (file)
@@ -829,7 +829,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 {
        scsi_qla_host_t *vha = shost_priv(cmd->device->host);
        srb_t *sp;
-       int ret;
+       int ret = SUCCESS;
        unsigned int id, lun;
        unsigned long flags;
        int wait = 0;
@@ -2064,6 +2064,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
                ha->gid_list_info_size = 8;
                ha->optrom_size = OPTROM_SIZE_82XX;
+               ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
                ha->isp_ops = &qla82xx_isp_ops;
                ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
                ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
index 8edbccb3232d3b68cb16d0054a444e657a452975..cf0075a2d0c2e66d93146bd92d95a5811f021327 100644 (file)
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.04-k0"
+#define QLA2XXX_VERSION      "8.03.05-k0"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   3
-#define QLA_DRIVER_PATCH_VER   4
+#define QLA_DRIVER_PATCH_VER   5
 #define QLA_DRIVER_BETA_VER    0
index 824b8fc03ce52f087dd3ca4d0fdadab15dfcac17..30ac116186f5106f61415cbdd9ee0b67a3f3b88e 100644 (file)
@@ -615,7 +615,7 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
        return rtn;
 }
 
-static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
 {
        if (!scmd->device->host->hostt->eh_abort_handler)
                return FAILED;
@@ -623,31 +623,9 @@ static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
        return scmd->device->host->hostt->eh_abort_handler(scmd);
 }
 
-/**
- * scsi_try_to_abort_cmd - Ask host to abort a running command.
- * @scmd:      SCSI cmd to abort from Lower Level.
- *
- * Notes:
- *    This function will not return until the user's completion function
- *    has been called.  there is no timeout on this operation.  if the
- *    author of the low-level driver wishes this operation to be timed,
- *    they can provide this facility themselves.  helper functions in
- *    scsi_error.c can be supplied to make this easier to do.
- */
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
-{
-       /*
-        * scsi_done was called just after the command timed out and before
-        * we had a chance to process it. (db)
-        */
-       if (scmd->serial_number == 0)
-               return SUCCESS;
-       return __scsi_try_to_abort_cmd(scmd);
-}
-
 static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
-       if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+       if (scsi_try_to_abort_cmd(scmd) != SUCCESS)
                if (scsi_try_bus_device_reset(scmd) != SUCCESS)
                        if (scsi_try_target_reset(scmd) != SUCCESS)
                                if (scsi_try_bus_reset(scmd) != SUCCESS)
index eafeeda6e1942b7deda691f940c0f10efddee390..5b6bbaea59fec92565d2af4d708cedce034295ae 100644 (file)
@@ -1403,11 +1403,6 @@ static void scsi_softirq_done(struct request *rq)
 
        INIT_LIST_HEAD(&cmd->eh_entry);
 
-       /*
-        * Set the serial numbers back to zero
-        */
-       cmd->serial_number = 0;
-
        atomic_inc(&cmd->device->iodone_cnt);
        if (cmd->result)
                atomic_inc(&cmd->device->ioerr_cnt);
index 3374618300af87c16ac3ef6a674e9cb650e62f8c..25a8bc565f400b62c155dd31bb39ff08e8d85dd0 100644 (file)
@@ -90,7 +90,8 @@ static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
 
 static void kgdboc_restore_input(void)
 {
-       schedule_work(&kgdboc_restore_input_work);
+       if (likely(system_state == SYSTEM_RUNNING))
+               schedule_work(&kgdboc_restore_input_work);
 }
 
 static int kgdboc_register_kbd(char **cptr)
index 90439314cf673ce19c33747ab4f283f0f3f0bc01..0838c79861e49f9a0c97189af9ab25d3c0269b76 100644 (file)
@@ -413,6 +413,11 @@ static void poll_transfer(struct dw_spi *dws)
 {
        while (dws->write(dws))
                dws->read(dws);
+       /*
+        * There is a possibility that the last word of a transaction
+        * will be lost if data is not ready. Re-read to solve this issue.
+        */
+       dws->read(dws);
 
        transfer_complete(dws);
 }
index 67eb3770868fbbb09b94ab26c6f0fc1a96ed13c0..5a7c8f1d76c6e4994b629826c6395176e9a7eb75 100644 (file)
@@ -41,6 +41,7 @@ config USB_ARCH_HAS_OHCI
        default y if MFD_TC6393XB
        default y if ARCH_W90X900
        default y if ARCH_DAVINCI_DA8XX
+       default y if ARCH_CNS3XXX
        # PPC:
        default y if STB03xxx
        default y if PPC_MPC52xx
@@ -66,6 +67,7 @@ config USB_ARCH_HAS_EHCI
        default y if ARCH_AT91SAM9G45
        default y if ARCH_MXC
        default y if ARCH_OMAP3
+       default y if ARCH_CNS3XXX
        default PCI
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
index 05bf5a27b5b0491fd7fd6feaddb24f51983317d3..989e16e4ab5c4b4057f2069927d03474e8441a5c 100644 (file)
@@ -951,7 +951,9 @@ static int usbatm_atm_init(struct usbatm_data *instance)
         * condition: callbacks we register can be executed at once, before we have
         * initialized the struct atm_dev.  To protect against this, all callbacks
         * abort if atm_dev->dev_data is NULL. */
-       atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
+       atm_dev = atm_dev_register(instance->driver_name,
+                                  &instance->usb_intf->dev, &usbatm_atm_devops,
+                                  -1, NULL);
        if (!atm_dev) {
                usb_err(instance, "%s: failed to register ATM device!\n", __func__);
                return -1;
@@ -966,14 +968,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
        /* temp init ATM device, set to 128kbit */
        atm_dev->link_rate = 128 * 1000 / 424;
 
-       ret = sysfs_create_link(&atm_dev->class_dev.kobj,
-                               &instance->usb_intf->dev.kobj, "device");
-       if (ret) {
-               atm_err(instance, "%s: sysfs_create_link failed: %d\n",
-                                       __func__, ret);
-               goto fail_sysfs;
-       }
-
        if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
                atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
                goto fail;
@@ -992,8 +986,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
        return 0;
 
  fail:
-       sysfs_remove_link(&atm_dev->class_dev.kobj, "device");
- fail_sysfs:
        instance->atm_dev = NULL;
        atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
        return ret;
@@ -1329,7 +1321,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
 
        /* ATM finalize */
        if (instance->atm_dev) {
-               sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
                atm_dev_deregister(instance->atm_dev);
                instance->atm_dev = NULL;
        }
index 6f4f8e6a40c7e2d1fe034ce3ddb056696fc0be00..f8970d151d2a61806a8f10f87b20b6446fad794d 100644 (file)
@@ -147,6 +147,14 @@ config USB_W90X900_EHCI
        ---help---
                Enables support for the W90X900 USB controller
 
+config USB_CNS3XXX_EHCI
+       bool "Cavium CNS3XXX EHCI Module"
+       depends on USB_EHCI_HCD && ARCH_CNS3XXX
+       ---help---
+         Enable support for the CNS3XXX SOC's on-chip EHCI controller.
+         It is needed for high-speed (480Mbit/sec) USB 2.0 device
+         support.
+
 config USB_OXU210HP_HCD
        tristate "OXU210HP HCD support"
        depends on USB
@@ -286,6 +294,13 @@ config USB_OHCI_HCD_SSB
 
          If unsure, say N.
 
+config USB_CNS3XXX_OHCI
+       bool "Cavium CNS3XXX OHCI Module"
+       depends on USB_OHCI_HCD && ARCH_CNS3XXX
+       ---help---
+         Enable support for the CNS3XXX SOC's on-chip OHCI controller.
+         It is needed for low-speed USB 1.0 device support.
+
 config USB_OHCI_BIG_ENDIAN_DESC
        bool
        depends on USB_OHCI_HCD
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
new file mode 100644 (file)
index 0000000..708a05b
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2008 Cavium Networks
+ *
+ * This file 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/platform_device.h>
+#include <linux/atomic.h>
+#include <mach/cns3xxx.h>
+#include <mach/pm.h>
+
+static int cns3xxx_ehci_init(struct usb_hcd *hcd)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       int retval;
+
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        *
+        * Set USB AHB INCR length to 16
+        */
+       if (atomic_inc_return(&usb_pwr_ref) == 1) {
+               cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+               cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+               cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+               __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+                       MISC_CHIP_CONFIG_REG);
+       }
+
+       ehci->caps = hcd->regs;
+       ehci->regs = hcd->regs
+               + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+       hcd->has_tt = 0;
+       ehci_reset(ehci);
+
+       retval = ehci_init(hcd);
+       if (retval)
+               return retval;
+
+       ehci_port_power(ehci, 0);
+
+       return retval;
+}
+
+static const struct hc_driver cns3xxx_ehci_hc_driver = {
+       .description            = hcd_name,
+       .product_desc           = "CNS3XXX EHCI Host Controller",
+       .hcd_priv_size          = sizeof(struct ehci_hcd),
+       .irq                    = ehci_irq,
+       .flags                  = HCD_MEMORY | HCD_USB2,
+       .reset                  = cns3xxx_ehci_init,
+       .start                  = ehci_run,
+       .stop                   = ehci_stop,
+       .shutdown               = ehci_shutdown,
+       .urb_enqueue            = ehci_urb_enqueue,
+       .urb_dequeue            = ehci_urb_dequeue,
+       .endpoint_disable       = ehci_endpoint_disable,
+       .endpoint_reset         = ehci_endpoint_reset,
+       .get_frame_number       = ehci_get_frame,
+       .hub_status_data        = ehci_hub_status_data,
+       .hub_control            = ehci_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend            = ehci_bus_suspend,
+       .bus_resume             = ehci_bus_resume,
+#endif
+       .relinquish_port        = ehci_relinquish_port,
+       .port_handed_over       = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
+};
+
+static int cns3xxx_ehci_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct usb_hcd *hcd;
+       const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
+       struct resource *res;
+       int irq;
+       int retval;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(dev, "Found HC with no IRQ.\n");
+               return -ENODEV;
+       }
+       irq = res->start;
+
+       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "Found HC with no register addr.\n");
+               retval = -ENODEV;
+               goto err1;
+       }
+
+       hcd->rsrc_start = res->start;
+       hcd->rsrc_len = res->end - res->start + 1;
+
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+                               driver->description)) {
+               dev_dbg(dev, "controller already in use\n");
+               retval = -EBUSY;
+               goto err1;
+       }
+
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       if (hcd->regs == NULL) {
+               dev_dbg(dev, "error mapping memory\n");
+               retval = -EFAULT;
+               goto err2;
+       }
+
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       if (retval == 0)
+               return retval;
+
+       iounmap(hcd->regs);
+err2:
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+       usb_put_hcd(hcd);
+
+       return retval;
+}
+
+static int cns3xxx_ehci_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+       usb_remove_hcd(hcd);
+       iounmap(hcd->regs);
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        */
+       if (atomic_dec_return(&usb_pwr_ref) == 0)
+               cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+
+       usb_put_hcd(hcd);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+MODULE_ALIAS("platform:cns3xxx-ehci");
+
+static struct platform_driver cns3xxx_ehci_driver = {
+       .probe = cns3xxx_ehci_probe,
+       .remove = cns3xxx_ehci_remove,
+       .driver = {
+               .name = "cns3xxx-ehci",
+       },
+};
index e9062806d4a24898286240f139a2f28dadd8522c..d0c8f7c03e05d599dc126e65eb1a8b64df927813 100644 (file)
@@ -1216,6 +1216,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_octeon_driver
 #endif
 
+#ifdef CONFIG_USB_CNS3XXX_EHCI
+#include "ehci-cns3xxx.c"
+#define PLATFORM_DRIVER                cns3xxx_ehci_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
new file mode 100644 (file)
index 0000000..f05ef87
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2008 Cavium Networks
+ *
+ * This file 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/platform_device.h>
+#include <linux/atomic.h>
+#include <mach/cns3xxx.h>
+#include <mach/pm.h>
+
+static int __devinit
+cns3xxx_ohci_start(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int ret;
+
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        *
+        * Set USB AHB INCR length to 16
+        */
+       if (atomic_inc_return(&usb_pwr_ref) == 1) {
+               cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+               cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+               cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+               __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+                       MISC_CHIP_CONFIG_REG);
+       }
+
+       ret = ohci_init(ohci);
+       if (ret < 0)
+               return ret;
+
+       ohci->num_ports = 1;
+
+       ret = ohci_run(ohci);
+       if (ret < 0) {
+               err("can't start %s", hcd->self.bus_name);
+               ohci_stop(hcd);
+               return ret;
+       }
+       return 0;
+}
+
+static const struct hc_driver cns3xxx_ohci_hc_driver = {
+       .description            = hcd_name,
+       .product_desc           = "CNS3XXX OHCI Host controller",
+       .hcd_priv_size          = sizeof(struct ohci_hcd),
+       .irq                    = ohci_irq,
+       .flags                  = HCD_USB11 | HCD_MEMORY,
+       .start                  = cns3xxx_ohci_start,
+       .stop                   = ohci_stop,
+       .shutdown               = ohci_shutdown,
+       .urb_enqueue            = ohci_urb_enqueue,
+       .urb_dequeue            = ohci_urb_dequeue,
+       .endpoint_disable       = ohci_endpoint_disable,
+       .get_frame_number       = ohci_get_frame,
+       .hub_status_data        = ohci_hub_status_data,
+       .hub_control            = ohci_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend            = ohci_bus_suspend,
+       .bus_resume             = ohci_bus_resume,
+#endif
+       .start_port_reset       = ohci_start_port_reset,
+};
+
+static int cns3xxx_ohci_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct usb_hcd *hcd;
+       const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
+       struct resource *res;
+       int irq;
+       int retval;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(dev, "Found HC with no IRQ.\n");
+               return -ENODEV;
+       }
+       irq = res->start;
+
+       hcd = usb_create_hcd(driver, dev, dev_name(dev));
+       if (!hcd)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "Found HC with no register addr.\n");
+               retval = -ENODEV;
+               goto err1;
+       }
+       hcd->rsrc_start = res->start;
+       hcd->rsrc_len = res->end - res->start + 1;
+
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+                       driver->description)) {
+               dev_dbg(dev, "controller already in use\n");
+               retval = -EBUSY;
+               goto err1;
+       }
+
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       if (!hcd->regs) {
+               dev_dbg(dev, "error mapping memory\n");
+               retval = -EFAULT;
+               goto err2;
+       }
+
+       ohci_hcd_init(hcd_to_ohci(hcd));
+
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       if (retval == 0)
+               return retval;
+
+       iounmap(hcd->regs);
+err2:
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+       usb_put_hcd(hcd);
+       return retval;
+}
+
+static int cns3xxx_ohci_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+       usb_remove_hcd(hcd);
+       iounmap(hcd->regs);
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        */
+       if (atomic_dec_return(&usb_pwr_ref) == 0)
+               cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+
+       usb_put_hcd(hcd);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+MODULE_ALIAS("platform:cns3xxx-ohci");
+
+static struct platform_driver ohci_hcd_cns3xxx_driver = {
+       .probe = cns3xxx_ohci_probe,
+       .remove = cns3xxx_ohci_remove,
+       .driver = {
+               .name = "cns3xxx-ohci",
+       },
+};
index 5179acb7aa2fb08be16b4b5becbabeb449cd1911..5cb6731ba44381288b8e36b78bca5919b20667a5 100644 (file)
@@ -1111,6 +1111,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_octeon_driver
 #endif
 
+#ifdef CONFIG_USB_CNS3XXX_OHCI
+#include "ohci-cns3xxx.c"
+#define PLATFORM_DRIVER                ohci_hcd_cns3xxx_driver
+#endif
+
 #if    !defined(PCI_DRIVER) &&         \
        !defined(PLATFORM_DRIVER) &&    \
        !defined(OMAP1_PLATFORM_DRIVER) &&      \
index 94701ff3a23ad957a9c675bd3ccd74418c2f989e..159c77a5746fecfd6c6eeb687cf11e747e194fba 100644 (file)
@@ -884,6 +884,7 @@ static int log_write(void __user *log_base,
        int r;
        if (!write_length)
                return 0;
+       write_length += write_address % VHOST_PAGE_SIZE;
        write_address /= VHOST_PAGE_SIZE;
        for (;;) {
                u64 base = (u64)(unsigned long)log_base;
@@ -897,7 +898,7 @@ static int log_write(void __user *log_base,
                if (write_length <= VHOST_PAGE_SIZE)
                        break;
                write_length -= VHOST_PAGE_SIZE;
-               write_address += VHOST_PAGE_SIZE;
+               write_address += 1;
        }
        return r;
 }
index 27c1fb4b1e0d71f91dcdd7d528dafa3b3457cb32..ab77297fbed2f46fc7e56a46512a4eaeb428552c 100644 (file)
@@ -1850,6 +1850,16 @@ config FB_PXA_PARAMETERS
 
          <file:Documentation/fb/pxafb.txt> describes the available parameters.
 
+config PXA3XX_GCU
+       tristate "PXA3xx 2D graphics accelerator driver"
+       depends on FB_PXA
+       help
+         Kernelspace driver for the 2D graphics controller unit (GCU)
+         found on PXA3xx processors. There is a counterpart driver in the
+         DirectFB suite, see http://www.directfb.org/
+
+         If you compile this as a module, it will be called pxa3xx_gcu.
+
 config FB_MBX
        tristate "2700G LCD framebuffer support"
        depends on FB && ARCH_PXA
index 485e8ed1318c4bd0a055553f784b6c642ca6cf81..9260a898f3439efecbbff4230f4d8d5e88dcf6b4 100644 (file)
@@ -100,6 +100,7 @@ obj-$(CONFIG_FB_CIRRUS)               += cirrusfb.o
 obj-$(CONFIG_FB_ASILIANT)        += asiliantfb.o
 obj-$(CONFIG_FB_PXA)             += pxafb.o
 obj-$(CONFIG_FB_PXA168)                  += pxa168fb.o
+obj-$(CONFIG_PXA3XX_GCU)         += pxa3xx-gcu.o
 obj-$(CONFIG_FB_W100)            += w100fb.o
 obj-$(CONFIG_FB_TMIO)            += tmiofb.o
 obj-$(CONFIG_FB_AU1100)                  += au1100fb.o
index 0a4dbdc1693a4462bddb82cdf5e0b9ab5ec4bed2..de450c1fb86926f39190f052d7644d56f60ccc5d 100644 (file)
@@ -855,6 +855,7 @@ const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
                        abs(cmode->yres - mode->yres);
                if (diff > d) {
                        diff = d;
+                       diff_refresh = abs(cmode->refresh - mode->refresh);
                        best = cmode;
                } else if (diff == d) {
                        d = abs(cmode->refresh - mode->refresh);
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
new file mode 100644 (file)
index 0000000..b81168d
--- /dev/null
@@ -0,0 +1,772 @@
+/*
+ *  pxa3xx-gc.c - Linux kernel module for PXA3xx graphics controllers
+ *
+ *  This driver needs a DirectFB counterpart in user space, communication
+ *  is handled via mmap()ed memory areas and an ioctl.
+ *
+ *  Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *  Copyright (c) 2009 Janine Kropp <nin@directfb.org>
+ *  Copyright (c) 2009 Denis Oliver Kropp <dok@directfb.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * WARNING: This controller is attached to System Bus 2 of the PXA which
+ * needs its arbiter to be enabled explictly (CKENB & 1<<9).
+ * There is currently no way to do this from Linux, so you need to teach
+ * your bootloader for now.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+
+#include "pxa3xx-gcu.h"
+
+#define DRV_NAME       "pxa3xx-gcu"
+#define MISCDEV_MINOR  197
+
+#define REG_GCCR       0x00
+#define GCCR_SYNC_CLR  (1 << 9)
+#define GCCR_BP_RST    (1 << 8)
+#define GCCR_ABORT     (1 << 6)
+#define GCCR_STOP      (1 << 4)
+
+#define REG_GCISCR     0x04
+#define REG_GCIECR     0x08
+#define REG_GCRBBR     0x20
+#define REG_GCRBLR     0x24
+#define REG_GCRBHR     0x28
+#define REG_GCRBTR     0x2C
+#define REG_GCRBEXHR   0x30
+
+#define IE_EOB         (1 << 0)
+#define IE_EEOB                (1 << 5)
+#define IE_ALL         0xff
+
+#define SHARED_SIZE    PAGE_ALIGN(sizeof(struct pxa3xx_gcu_shared))
+
+/* #define PXA3XX_GCU_DEBUG */
+/* #define PXA3XX_GCU_DEBUG_TIMER */
+
+#ifdef PXA3XX_GCU_DEBUG
+#define QDUMP(msg)                                     \
+       do {                                            \
+               QPRINT(priv, KERN_DEBUG, msg);          \
+       } while (0)
+#else
+#define QDUMP(msg)     do {} while (0)
+#endif
+
+#define QERROR(msg)                                    \
+       do {                                            \
+               QPRINT(priv, KERN_ERR, msg);            \
+       } while (0)
+
+struct pxa3xx_gcu_batch {
+       struct pxa3xx_gcu_batch *next;
+       u32                     *ptr;
+       dma_addr_t               phys;
+       unsigned long            length;
+};
+
+struct pxa3xx_gcu_priv {
+       void __iomem             *mmio_base;
+       struct clk               *clk;
+       struct pxa3xx_gcu_shared *shared;
+       dma_addr_t                shared_phys;
+       struct resource          *resource_mem;
+       struct miscdevice         misc_dev;
+       struct file_operations    misc_fops;
+       wait_queue_head_t         wait_idle;
+       wait_queue_head_t         wait_free;
+       spinlock_t                spinlock;
+       struct timeval            base_time;
+
+       struct pxa3xx_gcu_batch *free;
+
+       struct pxa3xx_gcu_batch *ready;
+       struct pxa3xx_gcu_batch *ready_last;
+       struct pxa3xx_gcu_batch *running;
+};
+
+static inline unsigned long
+gc_readl(struct pxa3xx_gcu_priv *priv, unsigned int off)
+{
+       return __raw_readl(priv->mmio_base + off);
+}
+
+static inline void
+gc_writel(struct pxa3xx_gcu_priv *priv, unsigned int off, unsigned long val)
+{
+       __raw_writel(val, priv->mmio_base + off);
+}
+
+#define QPRINT(priv, level, msg)                                       \
+       do {                                                            \
+               struct timeval tv;                                      \
+               struct pxa3xx_gcu_shared *shared = priv->shared;        \
+               u32 base = gc_readl(priv, REG_GCRBBR);                  \
+                                                                       \
+               do_gettimeofday(&tv);                                   \
+                                                                       \
+               printk(level "%ld.%03ld.%03ld - %-17s: %-21s (%s, "     \
+                       "STATUS "                                       \
+                       "0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, "    \
+                       "T %5ld)\n",                                    \
+                       tv.tv_sec - priv->base_time.tv_sec,             \
+                       tv.tv_usec / 1000, tv.tv_usec % 1000,           \
+                       __func__, msg,                                  \
+                       shared->hw_running ? "running" : "   idle",     \
+                       gc_readl(priv, REG_GCISCR),                     \
+                       gc_readl(priv, REG_GCRBBR),                     \
+                       gc_readl(priv, REG_GCRBLR),                     \
+                       (gc_readl(priv, REG_GCRBEXHR) - base) / 4,      \
+                       (gc_readl(priv, REG_GCRBHR) - base) / 4,        \
+                       (gc_readl(priv, REG_GCRBTR) - base) / 4);       \
+       } while (0)
+
+static void
+pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
+{
+       QDUMP("RESET");
+
+       /* disable interrupts */
+       gc_writel(priv, REG_GCIECR, 0);
+
+       /* reset hardware */
+       gc_writel(priv, REG_GCCR, GCCR_ABORT);
+       gc_writel(priv, REG_GCCR, 0);
+
+       memset(priv->shared, 0, SHARED_SIZE);
+       priv->shared->buffer_phys = priv->shared_phys;
+       priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
+
+       do_gettimeofday(&priv->base_time);
+
+       /* set up the ring buffer pointers */
+       gc_writel(priv, REG_GCRBLR, 0);
+       gc_writel(priv, REG_GCRBBR, priv->shared_phys);
+       gc_writel(priv, REG_GCRBTR, priv->shared_phys);
+
+       /* enable all IRQs except EOB */
+       gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
+}
+
+static void
+dump_whole_state(struct pxa3xx_gcu_priv *priv)
+{
+       struct pxa3xx_gcu_shared *sh = priv->shared;
+       u32 base = gc_readl(priv, REG_GCRBBR);
+
+       QDUMP("DUMP");
+
+       printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
+               "%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
+               sh->hw_running ? "running" : "idle   ",
+               gc_readl(priv, REG_GCISCR),
+               gc_readl(priv, REG_GCRBBR),
+               gc_readl(priv, REG_GCRBLR),
+               (gc_readl(priv, REG_GCRBEXHR) - base) / 4,
+               (gc_readl(priv, REG_GCRBHR) - base) / 4,
+               (gc_readl(priv, REG_GCRBTR) - base) / 4);
+}
+
+static void
+flush_running(struct pxa3xx_gcu_priv *priv)
+{
+       struct pxa3xx_gcu_batch *running = priv->running;
+       struct pxa3xx_gcu_batch *next;
+
+       while (running) {
+               next = running->next;
+               running->next = priv->free;
+               priv->free = running;
+               running = next;
+       }
+
+       priv->running = NULL;
+}
+
+static void
+run_ready(struct pxa3xx_gcu_priv *priv)
+{
+       unsigned int num = 0;
+       struct pxa3xx_gcu_shared *shared = priv->shared;
+       struct pxa3xx_gcu_batch *ready = priv->ready;
+
+       QDUMP("Start");
+
+       BUG_ON(!ready);
+
+       shared->buffer[num++] = 0x05000000;
+
+       while (ready) {
+               shared->buffer[num++] = 0x00000001;
+               shared->buffer[num++] = ready->phys;
+               ready = ready->next;
+       }
+
+       shared->buffer[num++] = 0x05000000;
+       priv->running = priv->ready;
+       priv->ready = priv->ready_last = NULL;
+       gc_writel(priv, REG_GCRBLR, 0);
+       shared->hw_running = 1;
+
+       /* ring base address */
+       gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
+
+       /* ring tail address */
+       gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
+
+       /* ring length */
+       gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
+}
+
+static irqreturn_t
+pxa3xx_gcu_handle_irq(int irq, void *ctx)
+{
+       struct pxa3xx_gcu_priv *priv = ctx;
+       struct pxa3xx_gcu_shared *shared = priv->shared;
+       u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
+
+       QDUMP("-Interrupt");
+
+       if (!status)
+               return IRQ_NONE;
+
+       spin_lock(&priv->spinlock);
+       shared->num_interrupts++;
+
+       if (status & IE_EEOB) {
+               QDUMP(" [EEOB]");
+
+               flush_running(priv);
+               wake_up_all(&priv->wait_free);
+
+               if (priv->ready) {
+                       run_ready(priv);
+               } else {
+                       /* There is no more data prepared by the userspace.
+                        * Set hw_running = 0 and wait for the next userspace
+                        * kick-off */
+                       shared->num_idle++;
+                       shared->hw_running = 0;
+
+                       QDUMP(" '-> Idle.");
+
+                       /* set ring buffer length to zero */
+                       gc_writel(priv, REG_GCRBLR, 0);
+
+                       wake_up_all(&priv->wait_idle);
+               }
+
+               shared->num_done++;
+       } else {
+               QERROR(" [???]");
+               dump_whole_state(priv);
+       }
+
+       /* Clear the interrupt */
+       gc_writel(priv, REG_GCISCR, status);
+       spin_unlock(&priv->spinlock);
+
+       return IRQ_HANDLED;
+}
+
+static int
+pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
+{
+       int ret = 0;
+
+       QDUMP("Waiting for idle...");
+
+       /* Does not need to be atomic. There's a lock in user space,
+        * but anyhow, this is just for statistics. */
+       priv->shared->num_wait_idle++;
+
+       while (priv->shared->hw_running) {
+               int num = priv->shared->num_interrupts;
+               u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
+
+               ret = wait_event_interruptible_timeout(priv->wait_idle,
+                                       !priv->shared->hw_running, HZ*4);
+
+               if (ret < 0)
+                       break;
+
+               if (ret > 0)
+                       continue;
+
+               if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
+                   priv->shared->num_interrupts == num) {
+                       QERROR("TIMEOUT");
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+       }
+
+       QDUMP("done");
+
+       return ret;
+}
+
+static int
+pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
+{
+       int ret = 0;
+
+       QDUMP("Waiting for free...");
+
+       /* Does not need to be atomic. There's a lock in user space,
+        * but anyhow, this is just for statistics. */
+       priv->shared->num_wait_free++;
+
+       while (!priv->free) {
+               u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
+
+               ret = wait_event_interruptible_timeout(priv->wait_free,
+                                                      priv->free, HZ*4);
+
+               if (ret < 0)
+                       break;
+
+               if (ret > 0)
+                       continue;
+
+               if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
+                       QERROR("TIMEOUT");
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+       }
+
+       QDUMP("done");
+
+       return ret;
+}
+
+/* Misc device layer */
+
+static ssize_t
+pxa3xx_gcu_misc_write(struct file *filp, const char *buff,
+                     size_t count, loff_t *offp)
+{
+       int ret;
+       unsigned long flags;
+       struct pxa3xx_gcu_batch *buffer;
+       struct pxa3xx_gcu_priv *priv =
+               container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+
+       int words = count / 4;
+
+       /* Does not need to be atomic. There's a lock in user space,
+        * but anyhow, this is just for statistics. */
+       priv->shared->num_writes++;
+
+       priv->shared->num_words += words;
+
+       /* Last word reserved for batch buffer end command */
+       if (words >= PXA3XX_GCU_BATCH_WORDS)
+               return -E2BIG;
+
+       /* Wait for a free buffer */
+       if (!priv->free) {
+               ret = pxa3xx_gcu_wait_free(priv);
+               if (ret < 0)
+                       return ret;
+       }
+
+       /*
+        * Get buffer from free list
+        */
+       spin_lock_irqsave(&priv->spinlock, flags);
+
+       buffer = priv->free;
+       priv->free = buffer->next;
+
+       spin_unlock_irqrestore(&priv->spinlock, flags);
+
+
+       /* Copy data from user into buffer */
+       ret = copy_from_user(buffer->ptr, buff, words * 4);
+       if (ret) {
+               spin_lock_irqsave(&priv->spinlock, flags);
+               buffer->next = priv->free;
+               priv->free = buffer;
+               spin_unlock_irqrestore(&priv->spinlock, flags);
+               return ret;
+       }
+
+       buffer->length = words;
+
+       /* Append batch buffer end command */
+       buffer->ptr[words] = 0x01000000;
+
+       /*
+        * Add buffer to ready list
+        */
+       spin_lock_irqsave(&priv->spinlock, flags);
+
+       buffer->next = NULL;
+
+       if (priv->ready) {
+               BUG_ON(priv->ready_last == NULL);
+
+               priv->ready_last->next = buffer;
+       } else
+               priv->ready = buffer;
+
+       priv->ready_last = buffer;
+
+       if (!priv->shared->hw_running)
+               run_ready(priv);
+
+       spin_unlock_irqrestore(&priv->spinlock, flags);
+
+       return words * 4;
+}
+
+
+static long
+pxa3xx_gcu_misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       unsigned long flags;
+       struct pxa3xx_gcu_priv *priv =
+               container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+
+       switch (cmd) {
+       case PXA3XX_GCU_IOCTL_RESET:
+               spin_lock_irqsave(&priv->spinlock, flags);
+               pxa3xx_gcu_reset(priv);
+               spin_unlock_irqrestore(&priv->spinlock, flags);
+               return 0;
+
+       case PXA3XX_GCU_IOCTL_WAIT_IDLE:
+               return pxa3xx_gcu_wait_idle(priv);
+       }
+
+       return -ENOSYS;
+}
+
+static int
+pxa3xx_gcu_misc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       unsigned int size = vma->vm_end - vma->vm_start;
+       struct pxa3xx_gcu_priv *priv =
+               container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+
+       switch (vma->vm_pgoff) {
+       case 0:
+               /* hand out the shared data area */
+               if (size != SHARED_SIZE)
+                       return -EINVAL;
+
+               return dma_mmap_coherent(NULL, vma,
+                       priv->shared, priv->shared_phys, size);
+
+       case SHARED_SIZE >> PAGE_SHIFT:
+               /* hand out the MMIO base for direct register access
+                * from userspace */
+               if (size != resource_size(priv->resource_mem))
+                       return -EINVAL;
+
+               vma->vm_flags |= VM_IO;
+               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+               return io_remap_pfn_range(vma, vma->vm_start,
+                               priv->resource_mem->start >> PAGE_SHIFT,
+                               size, vma->vm_page_prot);
+       }
+
+       return -EINVAL;
+}
+
+
+#ifdef PXA3XX_GCU_DEBUG_TIMER
+static struct timer_list pxa3xx_gcu_debug_timer;
+
+static void pxa3xx_gcu_debug_timedout(unsigned long ptr)
+{
+       struct pxa3xx_gcu_priv *priv = (struct pxa3xx_gcu_priv *) ptr;
+
+       QERROR("Timer DUMP");
+
+       /* init the timer structure */
+       init_timer(&pxa3xx_gcu_debug_timer);
+       pxa3xx_gcu_debug_timer.function = pxa3xx_gcu_debug_timedout;
+       pxa3xx_gcu_debug_timer.data = ptr;
+       pxa3xx_gcu_debug_timer.expires = jiffies + 5*HZ; /* one second */
+
+       add_timer(&pxa3xx_gcu_debug_timer);
+}
+
+static void pxa3xx_gcu_init_debug_timer(void)
+{
+       pxa3xx_gcu_debug_timedout((unsigned long) &pxa3xx_gcu_debug_timer);
+}
+#else
+static inline void pxa3xx_gcu_init_debug_timer(void) {}
+#endif
+
+static int
+add_buffer(struct platform_device *dev,
+          struct pxa3xx_gcu_priv *priv)
+{
+       struct pxa3xx_gcu_batch *buffer;
+
+       buffer = kzalloc(sizeof(struct pxa3xx_gcu_batch), GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       buffer->ptr = dma_alloc_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
+                                        &buffer->phys, GFP_KERNEL);
+       if (!buffer->ptr) {
+               kfree(buffer);
+               return -ENOMEM;
+       }
+
+       buffer->next = priv->free;
+
+       priv->free = buffer;
+
+       return 0;
+}
+
+static void
+free_buffers(struct platform_device *dev,
+            struct pxa3xx_gcu_priv *priv)
+{
+       struct pxa3xx_gcu_batch *next, *buffer = priv->free;
+
+       while (buffer) {
+               next = buffer->next;
+
+               dma_free_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
+                                 buffer->ptr, buffer->phys);
+
+               kfree(buffer);
+
+               buffer = next;
+       }
+
+       priv->free = NULL;
+}
+
+static int __devinit
+pxa3xx_gcu_probe(struct platform_device *dev)
+{
+       int i, ret, irq;
+       struct resource *r;
+       struct pxa3xx_gcu_priv *priv;
+
+       priv = kzalloc(sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       for (i = 0; i < 8; i++) {
+               ret = add_buffer(dev, priv);
+               if (ret) {
+                       dev_err(&dev->dev, "failed to allocate DMA memory\n");
+                       goto err_free_priv;
+               }
+       }
+
+       init_waitqueue_head(&priv->wait_idle);
+       init_waitqueue_head(&priv->wait_free);
+       spin_lock_init(&priv->spinlock);
+
+       /* we allocate the misc device structure as part of our own allocation,
+        * so we can get a pointer to our priv structure later on with
+        * container_of(). This isn't really necessary as we have a fixed minor
+        * number anyway, but this is to avoid statics. */
+
+       priv->misc_fops.owner   = THIS_MODULE;
+       priv->misc_fops.write   = pxa3xx_gcu_misc_write;
+       priv->misc_fops.unlocked_ioctl = pxa3xx_gcu_misc_ioctl;
+       priv->misc_fops.mmap    = pxa3xx_gcu_misc_mmap;
+
+       priv->misc_dev.minor    = MISCDEV_MINOR,
+       priv->misc_dev.name     = DRV_NAME,
+       priv->misc_dev.fops     = &priv->misc_fops,
+
+       /* register misc device */
+       ret = misc_register(&priv->misc_dev);
+       if (ret < 0) {
+               dev_err(&dev->dev, "misc_register() for minor %d failed\n",
+                       MISCDEV_MINOR);
+               goto err_free_priv;
+       }
+
+       /* handle IO resources */
+       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (r == NULL) {
+               dev_err(&dev->dev, "no I/O memory resource defined\n");
+               ret = -ENODEV;
+               goto err_misc_deregister;
+       }
+
+       if (!request_mem_region(r->start, resource_size(r), dev->name)) {
+               dev_err(&dev->dev, "failed to request I/O memory\n");
+               ret = -EBUSY;
+               goto err_misc_deregister;
+       }
+
+       priv->mmio_base = ioremap_nocache(r->start, resource_size(r));
+       if (!priv->mmio_base) {
+               dev_err(&dev->dev, "failed to map I/O memory\n");
+               ret = -EBUSY;
+               goto err_free_mem_region;
+       }
+
+       /* allocate dma memory */
+       priv->shared = dma_alloc_coherent(&dev->dev, SHARED_SIZE,
+                                         &priv->shared_phys, GFP_KERNEL);
+
+       if (!priv->shared) {
+               dev_err(&dev->dev, "failed to allocate DMA memory\n");
+               ret = -ENOMEM;
+               goto err_free_io;
+       }
+
+       /* enable the clock */
+       priv->clk = clk_get(&dev->dev, NULL);
+       if (IS_ERR(priv->clk)) {
+               dev_err(&dev->dev, "failed to get clock\n");
+               ret = -ENODEV;
+               goto err_free_dma;
+       }
+
+       ret = clk_enable(priv->clk);
+       if (ret < 0) {
+               dev_err(&dev->dev, "failed to enable clock\n");
+               goto err_put_clk;
+       }
+
+       /* request the IRQ */
+       irq = platform_get_irq(dev, 0);
+       if (irq < 0) {
+               dev_err(&dev->dev, "no IRQ defined\n");
+               ret = -ENODEV;
+               goto err_put_clk;
+       }
+
+       ret = request_irq(irq, pxa3xx_gcu_handle_irq,
+                         IRQF_DISABLED, DRV_NAME, priv);
+       if (ret) {
+               dev_err(&dev->dev, "request_irq failed\n");
+               ret = -EBUSY;
+               goto err_put_clk;
+       }
+
+       platform_set_drvdata(dev, priv);
+       priv->resource_mem = r;
+       pxa3xx_gcu_reset(priv);
+       pxa3xx_gcu_init_debug_timer();
+
+       dev_info(&dev->dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
+                       (void *) r->start, (void *) priv->shared_phys,
+                       SHARED_SIZE, irq);
+       return 0;
+
+err_put_clk:
+       clk_disable(priv->clk);
+       clk_put(priv->clk);
+
+err_free_dma:
+       dma_free_coherent(&dev->dev, SHARED_SIZE,
+                       priv->shared, priv->shared_phys);
+
+err_free_io:
+       iounmap(priv->mmio_base);
+
+err_free_mem_region:
+       release_mem_region(r->start, resource_size(r));
+
+err_misc_deregister:
+       misc_deregister(&priv->misc_dev);
+
+err_free_priv:
+       platform_set_drvdata(dev, NULL);
+       free_buffers(dev, priv);
+       kfree(priv);
+       return ret;
+}
+
+static int __devexit
+pxa3xx_gcu_remove(struct platform_device *dev)
+{
+       struct pxa3xx_gcu_priv *priv = platform_get_drvdata(dev);
+       struct resource *r = priv->resource_mem;
+
+       pxa3xx_gcu_wait_idle(priv);
+
+       misc_deregister(&priv->misc_dev);
+       dma_free_coherent(&dev->dev, SHARED_SIZE,
+                       priv->shared, priv->shared_phys);
+       iounmap(priv->mmio_base);
+       release_mem_region(r->start, resource_size(r));
+       platform_set_drvdata(dev, NULL);
+       clk_disable(priv->clk);
+       free_buffers(dev, priv);
+       kfree(priv);
+
+       return 0;
+}
+
+static struct platform_driver pxa3xx_gcu_driver = {
+       .probe    = pxa3xx_gcu_probe,
+       .remove  = __devexit_p(pxa3xx_gcu_remove),
+       .driver  = {
+               .owner  = THIS_MODULE,
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init
+pxa3xx_gcu_init(void)
+{
+       return platform_driver_register(&pxa3xx_gcu_driver);
+}
+
+static void __exit
+pxa3xx_gcu_exit(void)
+{
+       platform_driver_unregister(&pxa3xx_gcu_driver);
+}
+
+module_init(pxa3xx_gcu_init);
+module_exit(pxa3xx_gcu_exit);
+
+MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(MISCDEV_MINOR);
+MODULE_AUTHOR("Janine Kropp <nin@directfb.org>, "
+               "Denis Oliver Kropp <dok@directfb.org>, "
+               "Daniel Mack <daniel@caiaq.de>");
diff --git a/drivers/video/pxa3xx-gcu.h b/drivers/video/pxa3xx-gcu.h
new file mode 100644 (file)
index 0000000..0428ed0
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __PXA3XX_GCU_H__
+#define __PXA3XX_GCU_H__
+
+#include <linux/types.h>
+
+/* Number of 32bit words in display list (ring buffer). */
+#define PXA3XX_GCU_BUFFER_WORDS  ((256 * 1024 - 256) / 4)
+
+/* To be increased when breaking the ABI */
+#define PXA3XX_GCU_SHARED_MAGIC  0x30000001
+
+#define PXA3XX_GCU_BATCH_WORDS   8192
+
+struct pxa3xx_gcu_shared {
+       u32            buffer[PXA3XX_GCU_BUFFER_WORDS];
+
+       bool           hw_running;
+
+       unsigned long  buffer_phys;
+
+       unsigned int   num_words;
+       unsigned int   num_writes;
+       unsigned int   num_done;
+       unsigned int   num_interrupts;
+       unsigned int   num_wait_idle;
+       unsigned int   num_wait_free;
+       unsigned int   num_idle;
+
+       u32            magic;
+};
+
+/* Initialization and synchronization.
+ * Hardware is started upon write(). */
+#define PXA3XX_GCU_IOCTL_RESET         _IO('G', 0)
+#define PXA3XX_GCU_IOCTL_WAIT_IDLE     _IO('G', 2)
+
+#endif /* __PXA3XX_GCU_H__ */
+
index c547cca26a266e962bbb760c0616e0846439d81d..51d2e4de34ebe58d4eb5d2c99d1fc1bb83f692f9 100644 (file)
@@ -696,6 +696,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
                                   __btree_submit_bio_done);
 }
 
+#ifdef CONFIG_MIGRATION
 static int btree_migratepage(struct address_space *mapping,
                        struct page *newpage, struct page *page)
 {
@@ -712,12 +713,9 @@ static int btree_migratepage(struct address_space *mapping,
        if (page_has_private(page) &&
            !try_to_release_page(page, GFP_KERNEL))
                return -EAGAIN;
-#ifdef CONFIG_MIGRATION
        return migrate_page(mapping, newpage, page);
-#else
-       return -ENOSYS;
-#endif
 }
+#endif
 
 static int btree_writepage(struct page *page, struct writeback_control *wbc)
 {
@@ -1009,7 +1007,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
        blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
        root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
                                     blocksize, generation);
-       BUG_ON(!root->node);
+       if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
+               free_extent_buffer(root->node);
+               return -EIO;
+       }
        root->commit_root = btrfs_root_node(root);
        return 0;
 }
index bcd59c7dfb574def82517a80affe6a9ddf756a92..227e5815d8382393d4adc4d0a340ee636bca9d3e 100644 (file)
@@ -429,6 +429,7 @@ err:
 
 static int cache_block_group(struct btrfs_block_group_cache *cache,
                             struct btrfs_trans_handle *trans,
+                            struct btrfs_root *root,
                             int load_cache_only)
 {
        struct btrfs_fs_info *fs_info = cache->fs_info;
@@ -442,9 +443,12 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 
        /*
         * We can't do the read from on-disk cache during a commit since we need
-        * to have the normal tree locking.
+        * to have the normal tree locking.  Also if we are currently trying to
+        * allocate blocks for the tree root we can't do the fast caching since
+        * we likely hold important locks.
         */
-       if (!trans->transaction->in_commit) {
+       if (!trans->transaction->in_commit &&
+           (root && root != root->fs_info->tree_root)) {
                spin_lock(&cache->lock);
                if (cache->cached != BTRFS_CACHE_NO) {
                        spin_unlock(&cache->lock);
@@ -2741,6 +2745,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
        struct btrfs_root *root = block_group->fs_info->tree_root;
        struct inode *inode = NULL;
        u64 alloc_hint = 0;
+       int dcs = BTRFS_DC_ERROR;
        int num_pages = 0;
        int retries = 0;
        int ret = 0;
@@ -2795,6 +2800,8 @@ again:
 
        spin_lock(&block_group->lock);
        if (block_group->cached != BTRFS_CACHE_FINISHED) {
+               /* We're not cached, don't bother trying to write stuff out */
+               dcs = BTRFS_DC_WRITTEN;
                spin_unlock(&block_group->lock);
                goto out_put;
        }
@@ -2821,6 +2828,8 @@ again:
        ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages,
                                              num_pages, num_pages,
                                              &alloc_hint);
+       if (!ret)
+               dcs = BTRFS_DC_SETUP;
        btrfs_free_reserved_data_space(inode, num_pages);
 out_put:
        iput(inode);
@@ -2828,10 +2837,7 @@ out_free:
        btrfs_release_path(root, path);
 out:
        spin_lock(&block_group->lock);
-       if (ret)
-               block_group->disk_cache_state = BTRFS_DC_ERROR;
-       else
-               block_group->disk_cache_state = BTRFS_DC_SETUP;
+       block_group->disk_cache_state = dcs;
        spin_unlock(&block_group->lock);
 
        return ret;
@@ -3037,7 +3043,13 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
 
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
 {
-       u64 num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       u64 num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
 
        if (num_devices == 1)
                flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
@@ -4080,7 +4092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                 * space back to the block group, otherwise we will leak space.
                 */
                if (!alloc && cache->cached == BTRFS_CACHE_NO)
-                       cache_block_group(cache, trans, 1);
+                       cache_block_group(cache, trans, NULL, 1);
 
                byte_in_group = bytenr - cache->key.objectid;
                WARN_ON(byte_in_group > cache->key.offset);
@@ -4930,11 +4942,31 @@ search:
                btrfs_get_block_group(block_group);
                search_start = block_group->key.objectid;
 
+               /*
+                * this can happen if we end up cycling through all the
+                * raid types, but we want to make sure we only allocate
+                * for the proper type.
+                */
+               if (!block_group_bits(block_group, data)) {
+                   u64 extra = BTRFS_BLOCK_GROUP_DUP |
+                               BTRFS_BLOCK_GROUP_RAID1 |
+                               BTRFS_BLOCK_GROUP_RAID10;
+
+                       /*
+                        * if they asked for extra copies and this block group
+                        * doesn't provide them, bail.  This does allow us to
+                        * fill raid0 from raid1.
+                        */
+                       if ((data & extra) && !(block_group->flags & extra))
+                               goto loop;
+               }
+
 have_block_group:
                if (unlikely(block_group->cached == BTRFS_CACHE_NO)) {
                        u64 free_percent;
 
-                       ret = cache_block_group(block_group, trans, 1);
+                       ret = cache_block_group(block_group, trans,
+                                               orig_root, 1);
                        if (block_group->cached == BTRFS_CACHE_FINISHED)
                                goto have_block_group;
 
@@ -4958,7 +4990,8 @@ have_block_group:
                        if (loop > LOOP_CACHING_NOWAIT ||
                            (loop > LOOP_FIND_IDEAL &&
                             atomic_read(&space_info->caching_threads) < 2)) {
-                               ret = cache_block_group(block_group, trans, 0);
+                               ret = cache_block_group(block_group, trans,
+                                                       orig_root, 0);
                                BUG_ON(ret);
                        }
                        found_uncached_bg = true;
@@ -5515,7 +5548,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
        u64 num_bytes = ins->offset;
 
        block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
-       cache_block_group(block_group, trans, 0);
+       cache_block_group(block_group, trans, NULL, 0);
        caching_ctl = get_caching_control(block_group);
 
        if (!caching_ctl) {
@@ -6300,9 +6333,13 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                                           NULL, NULL);
                BUG_ON(ret < 0);
                if (ret > 0) {
-                       ret = btrfs_del_orphan_item(trans, tree_root,
-                                                   root->root_key.objectid);
-                       BUG_ON(ret);
+                       /* if we fail to delete the orphan item this time
+                        * around, it'll get picked up the next time.
+                        *
+                        * The most common failure here is just -ENOENT.
+                        */
+                       btrfs_del_orphan_item(trans, tree_root,
+                                             root->root_key.objectid);
                }
        }
 
@@ -7878,7 +7915,14 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
        u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
                BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
 
-       num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
+
        if (num_devices == 1) {
                stripped |= BTRFS_BLOCK_GROUP_DUP;
                stripped = flags & ~stripped;
@@ -8247,7 +8291,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                        break;
                if (ret != 0)
                        goto error;
-
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                cache = kzalloc(sizeof(*cache), GFP_NOFS);
index c1faded5fca03a7cbcb509908cfdf3cc8362ce1f..66836d85763bbfd2dafe3821a1be30f173784fdc 100644 (file)
@@ -48,30 +48,34 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
                                         struct page **prepared_pages,
                                         struct iov_iter *i)
 {
-       size_t copied;
+       size_t copied = 0;
        int pg = 0;
        int offset = pos & (PAGE_CACHE_SIZE - 1);
+       int total_copied = 0;
 
        while (write_bytes > 0) {
                size_t count = min_t(size_t,
                                     PAGE_CACHE_SIZE - offset, write_bytes);
                struct page *page = prepared_pages[pg];
-again:
-               if (unlikely(iov_iter_fault_in_readable(i, count)))
-                       return -EFAULT;
-
-               /* Copy data from userspace to the current page */
-               copied = iov_iter_copy_from_user(page, i, offset, count);
+               /*
+                * Copy data from userspace to the current page
+                *
+                * Disable pagefault to avoid recursive lock since
+                * the pages are already locked
+                */
+               pagefault_disable();
+               copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
+               pagefault_enable();
 
                /* Flush processor's dcache for this page */
                flush_dcache_page(page);
                iov_iter_advance(i, copied);
                write_bytes -= copied;
+               total_copied += copied;
 
+               /* Return to btrfs_file_aio_write to fault page */
                if (unlikely(copied == 0)) {
-                       count = min_t(size_t, PAGE_CACHE_SIZE - offset,
-                                     iov_iter_single_seg_count(i));
-                       goto again;
+                       break;
                }
 
                if (unlikely(copied < PAGE_CACHE_SIZE - offset)) {
@@ -81,7 +85,7 @@ again:
                        offset = 0;
                }
        }
-       return 0;
+       return total_copied;
 }
 
 /*
@@ -854,6 +858,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        unsigned long last_index;
        int will_write;
        int buffered = 0;
+       int copied = 0;
+       int dirty_pages = 0;
 
        will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
                      (file->f_flags & O_DIRECT));
@@ -970,7 +976,17 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                WARN_ON(num_pages > nrptrs);
                memset(pages, 0, sizeof(struct page *) * nrptrs);
 
-               ret = btrfs_delalloc_reserve_space(inode, write_bytes);
+               /*
+                * Fault pages before locking them in prepare_pages
+                * to avoid recursive lock
+                */
+               if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               ret = btrfs_delalloc_reserve_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                if (ret)
                        goto out;
 
@@ -978,37 +994,49 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                                    pos, first_index, last_index,
                                    write_bytes);
                if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
+                       btrfs_delalloc_release_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                        goto out;
                }
 
-               ret = btrfs_copy_from_user(pos, num_pages,
+               copied = btrfs_copy_from_user(pos, num_pages,
                                           write_bytes, pages, &i);
-               if (ret == 0) {
+               dirty_pages = (copied + PAGE_CACHE_SIZE - 1) >>
+                                       PAGE_CACHE_SHIFT;
+
+               if (num_pages > dirty_pages) {
+                       if (copied > 0)
+                               atomic_inc(
+                                       &BTRFS_I(inode)->outstanding_extents);
+                       btrfs_delalloc_release_space(inode,
+                                       (num_pages - dirty_pages) <<
+                                       PAGE_CACHE_SHIFT);
+               }
+
+               if (copied > 0) {
                        dirty_and_release_pages(NULL, root, file, pages,
-                                               num_pages, pos, write_bytes);
+                                               dirty_pages, pos, copied);
                }
 
                btrfs_drop_pages(pages, num_pages);
-               if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
-                       goto out;
-               }
 
-               if (will_write) {
-                       filemap_fdatawrite_range(inode->i_mapping, pos,
-                                                pos + write_bytes - 1);
-               } else {
-                       balance_dirty_pages_ratelimited_nr(inode->i_mapping,
-                                                          num_pages);
-                       if (num_pages <
-                           (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
-                               btrfs_btree_balance_dirty(root, 1);
-                       btrfs_throttle(root);
+               if (copied > 0) {
+                       if (will_write) {
+                               filemap_fdatawrite_range(inode->i_mapping, pos,
+                                                        pos + copied - 1);
+                       } else {
+                               balance_dirty_pages_ratelimited_nr(
+                                                       inode->i_mapping,
+                                                       dirty_pages);
+                               if (dirty_pages <
+                               (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
+                                       btrfs_btree_balance_dirty(root, 1);
+                               btrfs_throttle(root);
+                       }
                }
 
-               pos += write_bytes;
-               num_written += write_bytes;
+               pos += copied;
+               num_written += copied;
 
                cond_resched();
        }
index 22ee0dc2e6b8a712900c68a8c44df4a453fb86f0..60d684266959bbf8f96c14873e9a1f57e069a29e 100644 (file)
@@ -290,7 +290,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
                       (unsigned long long)BTRFS_I(inode)->generation,
                       (unsigned long long)generation,
                       (unsigned long long)block_group->key.objectid);
-               goto out;
+               goto free_cache;
        }
 
        if (!num_entries)
@@ -524,6 +524,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                return 0;
        }
 
+       node = rb_first(&block_group->free_space_offset);
+       if (!node) {
+               iput(inode);
+               return 0;
+       }
+
        last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
        filemap_write_and_wait(inode->i_mapping);
        btrfs_wait_ordered_range(inode, inode->i_size &
@@ -543,10 +549,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
         */
        first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
 
-       node = rb_first(&block_group->free_space_offset);
-       if (!node)
-               goto out_free;
-
        /*
         * Lock all pages first so we can lock the extent safely.
         *
index 8039390bd6a6f7bc1d1026d917dcaeb93aa067e6..72f31ecb5c90085a2d6adfdc9b690ee038bf508f 100644 (file)
@@ -495,7 +495,7 @@ again:
                add_async_extent(async_cow, start, num_bytes,
                                 total_compressed, pages, nr_pages_ret);
 
-               if (start + num_bytes < end && start + num_bytes < actual_end) {
+               if (start + num_bytes < end) {
                        start += num_bytes;
                        pages = NULL;
                        cond_resched();
@@ -5712,9 +5712,9 @@ static void btrfs_end_dio_bio(struct bio *bio, int err)
 
        if (err) {
                printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu "
-                     "disk_bytenr %lu len %u err no %d\n",
-                     dip->inode->i_ino, bio->bi_rw, bio->bi_sector,
-                     bio->bi_size, err);
+                     "sector %#Lx len %u err no %d\n",
+                     dip->inode->i_ino, bio->bi_rw,
+                     (unsigned long long)bio->bi_sector, bio->bi_size, err);
                dip->errors = 1;
 
                /*
@@ -5934,8 +5934,7 @@ free_ordered:
         */
        if (write) {
                struct btrfs_ordered_extent *ordered;
-               ordered = btrfs_lookup_ordered_extent(inode,
-                                                     dip->logical_offset);
+               ordered = btrfs_lookup_ordered_extent(inode, file_offset);
                if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) &&
                    !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags))
                        btrfs_free_reserved_extent(root, ordered->start,
index f1c9bb4079ed8b3aaf2a01bb5211923f8e231986..f87552a1d7ea0beeb540aa59ddac3754242304cc 100644 (file)
@@ -947,23 +947,42 @@ out:
 
 static noinline int btrfs_ioctl_snap_create(struct file *file,
                                            void __user *arg, int subvol,
-                                           int async)
+                                           int v2)
 {
        struct btrfs_ioctl_vol_args *vol_args = NULL;
-       struct btrfs_ioctl_async_vol_args *async_vol_args = NULL;
+       struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL;
        char *name;
        u64 fd;
-       u64 transid = 0;
        int ret;
 
-       if (async) {
-               async_vol_args = memdup_user(arg, sizeof(*async_vol_args));
-               if (IS_ERR(async_vol_args))
-                       return PTR_ERR(async_vol_args);
+       if (v2) {
+               u64 transid = 0;
+               u64 *ptr = NULL;
 
-               name = async_vol_args->name;
-               fd = async_vol_args->fd;
-               async_vol_args->name[BTRFS_SNAPSHOT_NAME_MAX] = '\0';
+               vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2));
+               if (IS_ERR(vol_args_v2))
+                       return PTR_ERR(vol_args_v2);
+
+               if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               name = vol_args_v2->name;
+               fd = vol_args_v2->fd;
+               vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
+
+               if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC)
+                       ptr = &transid;
+
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, ptr);
+
+               if (ret == 0 && ptr &&
+                   copy_to_user(arg +
+                                offsetof(struct btrfs_ioctl_vol_args_v2,
+                                         transid), ptr, sizeof(*ptr)))
+                       ret = -EFAULT;
        } else {
                vol_args = memdup_user(arg, sizeof(*vol_args));
                if (IS_ERR(vol_args))
@@ -971,20 +990,13 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
                name = vol_args->name;
                fd = vol_args->fd;
                vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
-       }
-
-       ret = btrfs_ioctl_snap_create_transid(file, name, fd,
-                                             subvol, &transid);
 
-       if (!ret && async) {
-               if (copy_to_user(arg +
-                               offsetof(struct btrfs_ioctl_async_vol_args,
-                               transid), &transid, sizeof(transid)))
-                       return -EFAULT;
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, NULL);
        }
-
+out:
        kfree(vol_args);
-       kfree(async_vol_args);
+       kfree(vol_args_v2);
 
        return ret;
 }
@@ -2246,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_getversion(file, argp);
        case BTRFS_IOC_SNAP_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 0, 0);
-       case BTRFS_IOC_SNAP_CREATE_ASYNC:
+       case BTRFS_IOC_SNAP_CREATE_V2:
                return btrfs_ioctl_snap_create(file, argp, 0, 1);
        case BTRFS_IOC_SUBVOL_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 1, 0);
index 17c99ebdf96049a8ad028cd6e138355df86f0c9e..c344d12c646bf7d1cbb953f8c4aba6257b6db8b9 100644 (file)
@@ -30,11 +30,15 @@ struct btrfs_ioctl_vol_args {
        char name[BTRFS_PATH_NAME_MAX + 1];
 };
 
-#define BTRFS_SNAPSHOT_NAME_MAX 4079
-struct btrfs_ioctl_async_vol_args {
+#define BTRFS_SUBVOL_CREATE_ASYNC      (1ULL << 0)
+
+#define BTRFS_SUBVOL_NAME_MAX 4039
+struct btrfs_ioctl_vol_args_v2 {
        __s64 fd;
        __u64 transid;
-       char name[BTRFS_SNAPSHOT_NAME_MAX + 1];
+       __u64 flags;
+       __u64 unused[4];
+       char name[BTRFS_SUBVOL_NAME_MAX + 1];
 };
 
 #define BTRFS_INO_LOOKUP_PATH_MAX 4080
@@ -187,6 +191,6 @@ struct btrfs_ioctl_space_args {
                                    struct btrfs_ioctl_space_args)
 #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
 #define BTRFS_IOC_WAIT_SYNC  _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
-#define BTRFS_IOC_SNAP_CREATE_ASYNC _IOW(BTRFS_IOCTL_MAGIC, 23, \
-                                  struct btrfs_ioctl_async_vol_args)
+#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
+                                  struct btrfs_ioctl_vol_args_v2)
 #endif
index 79cba5fbc28ef8061e2d599110a3a525216a7bfd..f8be250963a09a283b8ec4ab04bcb1c3a962427e 100644 (file)
@@ -56,8 +56,12 @@ int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
                return -ENOMEM;
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-       if (ret)
+       if (ret < 0)
                goto out;
+       if (ret) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        ret = btrfs_del_item(trans, root, path);
 
index dbb51ea7a13c4b83e46c6c1f03d8d936cf75bed7..883c6fa1367eb866002d7f67d3ae2ce6497f4367 100644 (file)
@@ -685,9 +685,9 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                mutex_unlock(&root->d_inode->i_mutex);
 
                if (IS_ERR(new_root)) {
+                       dput(root);
                        deactivate_locked_super(s);
                        error = PTR_ERR(new_root);
-                       dput(root);
                        goto error_free_subvol_name;
                }
                if (!new_root->d_inode) {
index cc04dc1445d64da8694401c2cbc2fde27105b8f9..6b9884507837581ba6231bc6c4cfb85a036b82f6 100644 (file)
@@ -412,12 +412,16 @@ static noinline int device_list_add(const char *path,
 
                device->fs_devices = fs_devices;
                fs_devices->num_devices++;
-       } else if (strcmp(device->name, path)) {
+       } else if (!device->name || strcmp(device->name, path)) {
                name = kstrdup(path, GFP_NOFS);
                if (!name)
                        return -ENOMEM;
                kfree(device->name);
                device->name = name;
+               if (device->missing) {
+                       fs_devices->missing_devices--;
+                       device->missing = 0;
+               }
        }
 
        if (found_transid > fs_devices->latest_trans) {
@@ -1236,6 +1240,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 
        device->fs_devices->num_devices--;
 
+       if (device->missing)
+               root->fs_info->fs_devices->missing_devices--;
+
        next_device = list_entry(root->fs_info->fs_devices->devices.next,
                                 struct btrfs_device, dev_list);
        if (device->bdev == root->fs_info->sb->s_bdev)
@@ -3080,7 +3087,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
        device->devid = devid;
        device->work.func = pending_bios_fn;
        device->fs_devices = fs_devices;
+       device->missing = 1;
        fs_devices->num_devices++;
+       fs_devices->missing_devices++;
        spin_lock_init(&device->io_lock);
        INIT_LIST_HEAD(&device->dev_alloc_list);
        memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE);
@@ -3278,6 +3287,15 @@ static int read_one_dev(struct btrfs_root *root,
                        device = add_missing_dev(root, devid, dev_uuid);
                        if (!device)
                                return -ENOMEM;
+               } else if (!device->missing) {
+                       /*
+                        * this happens when a device that was properly setup
+                        * in the device info lists suddenly goes bad.
+                        * device->bdev is NULL, and so we have to set
+                        * device->missing to one here
+                        */
+                       root->fs_info->fs_devices->missing_devices++;
+                       device->missing = 1;
                }
        }
 
index 2b638b6e4eeae7cb9428490a897c1e10a9aaad1f..2740db49eb04d7a8de03d18e5935a97ff43ef9db 100644 (file)
@@ -44,6 +44,7 @@ struct btrfs_device {
 
        int writeable;
        int in_fs_metadata;
+       int missing;
 
        spinlock_t io_lock;
 
@@ -93,6 +94,7 @@ struct btrfs_fs_devices {
        u64 num_devices;
        u64 open_devices;
        u64 rw_devices;
+       u64 missing_devices;
        u64 total_rw_bytes;
        struct block_device *latest_bdev;
 
index 7d447af84ec4861acee8cd82bcecf80a892132b1..158c700fdca5e4f62763377a8374217d6371b68b 100644 (file)
@@ -114,8 +114,8 @@ static int __dcache_readdir(struct file *filp,
        spin_lock(&dcache_lock);
 
        /* start at beginning? */
-       if (filp->f_pos == 2 || (last &&
-                                filp->f_pos < ceph_dentry(last)->offset)) {
+       if (filp->f_pos == 2 || last == NULL ||
+           filp->f_pos < ceph_dentry(last)->offset) {
                if (list_empty(&parent->d_subdirs))
                        goto out_unlock;
                p = parent->d_subdirs.prev;
index a6ce54e94eb5ab435670093cd6ad789e72cc627b..52e8fd74d450b9e2895eb7c29d80e38b77eb0807 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-#define CEPH_IOCTL_MAGIC 0x98
+#define CEPH_IOCTL_MAGIC 0x97
 
 /* just use u64 to align sanely on all archs */
 struct ceph_ioctl_layout {
index 40abde93c345d054279fd51cbca998525c4931c7..476b329867d41cf2cec7b3e2ad51e5f3885d9d7a 100644 (file)
  * Implement fcntl and flock locking functions.
  */
 static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
-                            u64 pid, u64 pid_ns,
-                            int cmd, u64 start, u64 length, u8 wait)
+                            int cmd, u8 wait, struct file_lock *fl)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_mds_client *mdsc =
                ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_mds_request *req;
        int err;
+       u64 length = 0;
 
        req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
        req->r_inode = igrab(inode);
 
+       /* mds requires start and length rather than start and end */
+       if (LLONG_MAX == fl->fl_end)
+               length = 0;
+       else
+               length = fl->fl_end - fl->fl_start + 1;
+
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
             "length: %llu, wait: %d, type`: %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd);
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type);
+
 
        req->r_args.filelock_change.rule = lock_type;
        req->r_args.filelock_change.type = cmd;
-       req->r_args.filelock_change.pid = cpu_to_le64(pid);
+       req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid);
        /* This should be adjusted, but I'm not sure if
           namespaces actually get id numbers*/
        req->r_args.filelock_change.pid_namespace =
-               cpu_to_le64((u64)pid_ns);
-       req->r_args.filelock_change.start = cpu_to_le64(start);
+               cpu_to_le64((u64)(unsigned long)fl->fl_nspid);
+       req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start);
        req->r_args.filelock_change.length = cpu_to_le64(length);
        req->r_args.filelock_change.wait = wait;
 
        err = ceph_mdsc_do_request(mdsc, inode, req);
+
+       if ( operation == CEPH_MDS_OP_GETFILELOCK){
+               fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid);
+               if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_RDLCK;
+               else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_WRLCK;
+               else
+                       fl->fl_type = F_UNLCK;
+
+               fl->fl_start = le64_to_cpu(req->r_reply_info.filelock_reply->start);
+               length = le64_to_cpu(req->r_reply_info.filelock_reply->start) +
+                                                le64_to_cpu(req->r_reply_info.filelock_reply->length);
+               if (length >= 1)
+                       fl->fl_end = length -1;
+               else
+                       fl->fl_end = 0;
+
+       }
        ceph_mdsc_put_request(req);
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
-            "length: %llu, wait: %d, type`: %d err code %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd, err);
+            "length: %llu, wait: %d, type`: %d, err code %d", (int)lock_type,
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type, err);
        return err;
 }
 
@@ -54,7 +82,6 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
  */
 int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 0;
@@ -76,29 +103,20 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
 
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
-
-       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                               (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl);
        if (!err) {
-               dout("mds locked, locking locally");
-               err = posix_lock_file(file, fl, NULL);
-               if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
-                       /* undo! This should only happen if the kernel detects
-                        * local deadlock. */
-                       ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                                         (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
-                       dout("got %d on posix_lock_file, undid lock", err);
+               if ( op != CEPH_MDS_OP_GETFILELOCK ){
+                       dout("mds locked, locking locally");
+                       err = posix_lock_file(file, fl, NULL);
+                       if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
+                               /* undo! This should only happen if the kernel detects
+                                * local deadlock. */
+                               ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
+                                                 CEPH_LOCK_UNLOCK, 0, fl);
+                               dout("got %d on posix_lock_file, undid lock", err);
+                       }
                }
+
        } else {
                dout("mds returned error code %d", err);
        }
@@ -107,7 +125,6 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 
 int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 1;
@@ -127,26 +144,15 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
                lock_cmd = CEPH_LOCK_EXCL;
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
-       /* mds requires start and length rather than start and end */
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
 
        err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
-                               file, (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+                               file, lock_cmd, wait, fl);
        if (!err) {
                err = flock_lock_file_wait(file, fl);
                if (err) {
                        ceph_lock_message(CEPH_LOCK_FLOCK,
                                          CEPH_MDS_OP_SETFILELOCK,
-                                         file, (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
+                                         file, CEPH_LOCK_UNLOCK, 0, fl);
                        dout("got %d on flock_lock_file_wait, undid lock", err);
                }
        } else {
index 098b185084791730ba0143111126bc066fdb9afb..38800eaa81d066bd8f06a401d082ecd3bb3f6fea 100644 (file)
@@ -201,6 +201,38 @@ out_bad:
        return err;
 }
 
+/*
+ * parse fcntl F_GETLK results
+ */
+static int parse_reply_info_filelock(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (*p + sizeof(*info->filelock_reply) > end)
+               goto bad;
+
+       info->filelock_reply = *p;
+       *p += sizeof(*info->filelock_reply);
+
+       if (unlikely(*p != end))
+               goto bad;
+       return 0;
+
+bad:
+       return -EIO;
+}
+
+/*
+ * parse extra results
+ */
+static int parse_reply_info_extra(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
+               return parse_reply_info_filelock(p, end, info);
+       else
+               return parse_reply_info_dir(p, end, info);
+}
+
 /*
  * parse entire mds reply
  */
@@ -223,10 +255,10 @@ static int parse_reply_info(struct ceph_msg *msg,
                        goto out_bad;
        }
 
-       /* dir content */
+       /* extra */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
-               err = parse_reply_info_dir(&p, p+len, info);
+               err = parse_reply_info_extra(&p, p+len, info);
                if (err < 0)
                        goto out_bad;
        }
@@ -2074,7 +2106,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
 
        mutex_lock(&session->s_mutex);
        if (err < 0) {
-               pr_err("mdsc_handle_reply got corrupt reply mds%d\n", mds);
+               pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid);
                ceph_msg_dump(msg);
                goto out_err;
        }
@@ -2094,7 +2126,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        mutex_lock(&req->r_fill_mutex);
        err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
        if (err == 0) {
-               if (result == 0 && rinfo->dir_nr)
+               if (result == 0 && req->r_op != CEPH_MDS_OP_GETFILELOCK &&
+                   rinfo->dir_nr)
                        ceph_readdir_prepopulate(req, req->r_session);
                ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
        }
index 9341fd4f14320060a395c37f81b4a67b01c020d7..aabe563b54db308af80ee9fff18dd81610a9cf94 100644 (file)
@@ -42,26 +42,37 @@ struct ceph_mds_reply_info_in {
 };
 
 /*
- * parsed info about an mds reply, including information about the
- * target inode and/or its parent directory and dentry, and directory
- * contents (for readdir results).
+ * parsed info about an mds reply, including information about
+ * either: 1) the target inode and/or its parent directory and dentry,
+ * and directory contents (for readdir results), or
+ * 2) the file range lock info (for fcntl F_GETLK results).
  */
 struct ceph_mds_reply_info_parsed {
        struct ceph_mds_reply_head    *head;
 
+       /* trace */
        struct ceph_mds_reply_info_in diri, targeti;
        struct ceph_mds_reply_dirfrag *dirfrag;
        char                          *dname;
        u32                           dname_len;
        struct ceph_mds_reply_lease   *dlease;
 
-       struct ceph_mds_reply_dirfrag *dir_dir;
-       int                           dir_nr;
-       char                          **dir_dname;
-       u32                           *dir_dname_len;
-       struct ceph_mds_reply_lease   **dir_dlease;
-       struct ceph_mds_reply_info_in *dir_in;
-       u8                            dir_complete, dir_end;
+       /* extra */
+       union {
+               /* for fcntl F_GETLK results */
+               struct ceph_filelock *filelock_reply;
+
+               /* for readdir results */
+               struct {
+                       struct ceph_mds_reply_dirfrag *dir_dir;
+                       int                           dir_nr;
+                       char                          **dir_dname;
+                       u32                           *dir_dname_len;
+                       struct ceph_mds_reply_lease   **dir_dlease;
+                       struct ceph_mds_reply_info_in *dir_in;
+                       u8                            dir_complete, dir_end;
+               };
+       };
 
        /* encoded blob describing snapshot contexts for certain
           operations (e.g., open) */
index adefa60a9bdc10108ec9c802e4cbe1ea26f3f6e0..43b19dd391912476c395ffbabaaabbacc28d0146 100644 (file)
@@ -6,7 +6,9 @@ obj-$(CONFIG_CIFS) += cifs.o
 cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
          link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
          md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \
-         readdir.o ioctl.o sess.o export.o cifsacl.o
+         readdir.o ioctl.o sess.o export.o
+
+cifs-$(CONFIG_CIFS_ACL) += cifsacl.o
 
 cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
 
index ee68d1036544d591930af8119d5e7450634adfff..46af99ab3614d545675e41e788686b39fd51204b 100644 (file)
@@ -337,6 +337,15 @@ A partial list of the supported mount options follows:
   wsize                default write size (default 57344)
                maximum wsize currently allowed by CIFS is 57344 (fourteen
                4096 byte pages)
+  actimeo=n    attribute cache timeout in seconds (default 1 second).
+               After this timeout, the cifs client requests fresh attribute
+               information from the server. This option allows to tune the
+               attribute cache timeout to suit the workload needs. Shorter
+               timeouts mean better the cache coherency, but increased number
+               of calls to the server. Longer timeouts mean reduced number
+               of calls to the server at the expense of less stricter cache
+               coherency checks (i.e. incorrect attribute cache for a short
+               period of time).
   rw           mount the network share read-write (note that the
                server may still consider the share read-only)
   ro           mount network share read-only
index e9a393c9c2ca4ddb8ec3d75cfcf0766234ec1789..7852cd6770517a8a5da7877fb788a834a0534c86 100644 (file)
@@ -48,6 +48,7 @@ struct cifs_sb_info {
        struct nls_table *local_nls;
        unsigned int rsize;
        unsigned int wsize;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        atomic_t active;
        uid_t   mnt_uid;
        gid_t   mnt_gid;
index c6ebea088ac7c2bf6d01d3ac02910f0164a4b4b3..a437ec391a015fb7c05725543d6c118eadefc466 100644 (file)
@@ -30,8 +30,6 @@
 #include "cifs_debug.h"
 
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
        {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
        {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
@@ -774,4 +772,3 @@ int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
 
        return rc;
 }
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
index 6c8096cf51557764aa10af6c28d108d3e93ce6e7..c4ae7d0365631f5d01db610ef3153502f2531c9d 100644 (file)
@@ -74,11 +74,7 @@ struct cifs_wksid {
        char sidname[SIDNAMELENGTH];
 } __attribute__((packed));
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 extern int match_sid(struct cifs_sid *);
 extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
 
-#endif /*  CONFIG_CIFS_EXPERIMENTAL */
-
 #endif /* _CIFSACL_H */
index 76c8a906a63eee2369123f0ea1f433ad58692b1e..3936aa7f2c2285cfb59857f8fe1925528920543a 100644 (file)
@@ -463,6 +463,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 
        seq_printf(s, ",rsize=%d", cifs_sb->rsize);
        seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+       /* convert actimeo and display it in seconds */
+               seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
 
        return 0;
 }
@@ -935,7 +937,6 @@ init_cifs(void)
        GlobalCurrentXid = 0;
        GlobalTotalActiveXid = 0;
        GlobalMaxActiveXid = 0;
-       memset(Local_System_Name, 0, 15);
        spin_lock_init(&cifs_tcp_ses_lock);
        spin_lock_init(&cifs_file_list_lock);
        spin_lock_init(&GlobalMid_Lock);
index b577bf0a1bb3622491ed0a885ca30b9e7684d24e..7136c0c3e2f961ec2c57d882163a1ffbc0e50ef1 100644 (file)
 
 #define CIFS_MIN_RCV_POOL 4
 
+/*
+ * default attribute cache timeout (jiffies)
+ */
+#define CIFS_DEF_ACTIMEO (1 * HZ)
+
+/*
+ * max attribute cache timeout (jiffies) - 2^30
+ */
+#define CIFS_MAX_ACTIMEO (1 << 30)
+
 /*
  * MAX_REQ is the maximum number of requests that WE will send
  * on one socket concurrently. It also matches the most common
@@ -746,8 +756,6 @@ GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN spinlock_t GlobalMid_Lock;  /* protects above & list operations */
                                          /* on midQ entries */
-GLOBAL_EXTERN char Local_System_Name[15];
-
 /*
  *  Global counters, updated atomically
  */
index db961dc4fd3d30b4bbdf15924c1e58fded05b10e..e6d1481b16c1403cbe1c7fcae04e11abcc3f91f9 100644 (file)
@@ -54,7 +54,8 @@ do {                                                          \
             __func__, curr_xid, (int)rc);                      \
 } while (0)
 extern char *build_path_from_dentry(struct dentry *);
-extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
+extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                                       struct cifsTconInfo *tcon);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern char *cifs_compose_mount_options(const char *sb_mountdata,
                const char *fullpath, const struct dfs_info3_param *ref,
@@ -79,9 +80,7 @@ extern bool is_valid_oplock_break(struct smb_hdr *smb,
                                  struct TCP_Server_Info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
-#endif
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
index 2f2632b6df5a1efd960bf44502d280e0e9499908..67acfb3acad271a51be1a1446d4f9828119e6b39 100644 (file)
@@ -2478,95 +2478,6 @@ querySymLinkRetry:
 }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-/* Initialize NT TRANSACT SMB into small smb request buffer.
-   This assumes that all NT TRANSACTS that we init here have
-   total parm and data under about 400 bytes (to fit in small cifs
-   buffer size), which is the case so far, it easily fits. NB:
-       Setup words themselves and ByteCount
-       MaxSetupCount (size of returned setup area) and
-       MaxParameterCount (returned parms size) must be set by caller */
-static int
-smb_init_nttransact(const __u16 sub_command, const int setup_count,
-                  const int parm_len, struct cifsTconInfo *tcon,
-                  void **ret_buf)
-{
-       int rc;
-       __u32 temp_offset;
-       struct smb_com_ntransact_req *pSMB;
-
-       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
-                               (void **)&pSMB);
-       if (rc)
-               return rc;
-       *ret_buf = (void *)pSMB;
-       pSMB->Reserved = 0;
-       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
-       pSMB->TotalDataCount  = 0;
-       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
-                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->DataCount  = pSMB->TotalDataCount;
-       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
-                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
-       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
-       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
-       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
-       pSMB->SubCommand = cpu_to_le16(sub_command);
-       return 0;
-}
-
-static int
-validate_ntransact(char *buf, char **ppparm, char **ppdata,
-                  __u32 *pparmlen, __u32 *pdatalen)
-{
-       char *end_of_smb;
-       __u32 data_count, data_offset, parm_count, parm_offset;
-       struct smb_com_ntransact_rsp *pSMBr;
-
-       *pdatalen = 0;
-       *pparmlen = 0;
-
-       if (buf == NULL)
-               return -EINVAL;
-
-       pSMBr = (struct smb_com_ntransact_rsp *)buf;
-
-       /* ByteCount was converted from little endian in SendReceive */
-       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
-                       (char *)&pSMBr->ByteCount;
-
-       data_offset = le32_to_cpu(pSMBr->DataOffset);
-       data_count = le32_to_cpu(pSMBr->DataCount);
-       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
-       parm_count = le32_to_cpu(pSMBr->ParameterCount);
-
-       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
-       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
-
-       /* should we also check that parm and data areas do not overlap? */
-       if (*ppparm > end_of_smb) {
-               cFYI(1, "parms start after end of smb");
-               return -EINVAL;
-       } else if (parm_count + *ppparm > end_of_smb) {
-               cFYI(1, "parm end after end of smb");
-               return -EINVAL;
-       } else if (*ppdata > end_of_smb) {
-               cFYI(1, "data starts after end of smb");
-               return -EINVAL;
-       } else if (data_count + *ppdata > end_of_smb) {
-               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
-                       *ppdata, data_count, (data_count + *ppdata),
-                       end_of_smb, pSMBr);
-               return -EINVAL;
-       } else if (parm_count + data_count > pSMBr->ByteCount) {
-               cFYI(1, "parm count and data count larger than SMB");
-               return -EINVAL;
-       }
-       *pdatalen = data_count;
-       *pparmlen = parm_count;
-       return 0;
-}
-
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName,
@@ -3056,7 +2967,97 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
+/*
+ * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
+ * all NT TRANSACTS that we init here have total parm and data under about 400
+ * bytes (to fit in small cifs buffer size), which is the case so far, it
+ * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
+ * returned setup area) and MaxParameterCount (returned parms size) must be set
+ * by caller
+ */
+static int
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
+                  const int parm_len, struct cifsTconInfo *tcon,
+                  void **ret_buf)
+{
+       int rc;
+       __u32 temp_offset;
+       struct smb_com_ntransact_req *pSMB;
+
+       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+                               (void **)&pSMB);
+       if (rc)
+               return rc;
+       *ret_buf = (void *)pSMB;
+       pSMB->Reserved = 0;
+       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+       pSMB->TotalDataCount  = 0;
+       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->DataCount  = pSMB->TotalDataCount;
+       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
+       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+       pSMB->SubCommand = cpu_to_le16(sub_command);
+       return 0;
+}
+
+static int
+validate_ntransact(char *buf, char **ppparm, char **ppdata,
+                  __u32 *pparmlen, __u32 *pdatalen)
+{
+       char *end_of_smb;
+       __u32 data_count, data_offset, parm_count, parm_offset;
+       struct smb_com_ntransact_rsp *pSMBr;
+
+       *pdatalen = 0;
+       *pparmlen = 0;
+
+       if (buf == NULL)
+               return -EINVAL;
+
+       pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+       /* ByteCount was converted from little endian in SendReceive */
+       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
+                       (char *)&pSMBr->ByteCount;
+
+       data_offset = le32_to_cpu(pSMBr->DataOffset);
+       data_count = le32_to_cpu(pSMBr->DataCount);
+       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+       parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+       /* should we also check that parm and data areas do not overlap? */
+       if (*ppparm > end_of_smb) {
+               cFYI(1, "parms start after end of smb");
+               return -EINVAL;
+       } else if (parm_count + *ppparm > end_of_smb) {
+               cFYI(1, "parm end after end of smb");
+               return -EINVAL;
+       } else if (*ppdata > end_of_smb) {
+               cFYI(1, "data starts after end of smb");
+               return -EINVAL;
+       } else if (data_count + *ppdata > end_of_smb) {
+               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
+                       *ppdata, data_count, (data_count + *ppdata),
+                       end_of_smb, pSMBr);
+               return -EINVAL;
+       } else if (parm_count + data_count > pSMBr->ByteCount) {
+               cFYI(1, "parm count and data count larger than SMB");
+               return -EINVAL;
+       }
+       *pdatalen = data_count;
+       *pparmlen = parm_count;
+       return 0;
+}
+
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
@@ -3214,7 +3215,7 @@ setCifsAclRetry:
        return (rc);
 }
 
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
+#endif /* CONFIG_CIFS_ACL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
index 32fa4d9b5dbc11537dfc09653215a9540668e109..cc1a8604a790b46767e066a59ef897f314144163 100644 (file)
@@ -105,6 +105,7 @@ struct smb_vol {
        unsigned int wsize;
        bool sockopt_tcp_nodelay:1;
        unsigned short int port;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        char *prepath;
        struct sockaddr_storage srcaddr; /* allow binding to a local IP */
        struct nls_table *local_nls;
@@ -806,23 +807,20 @@ cifs_parse_mount_options(char *options, const char *devname,
        short int override_gid = -1;
        bool uid_specified = false;
        bool gid_specified = false;
+       char *nodename = utsname()->nodename;
 
        separator[0] = ',';
        separator[1] = 0;
 
-       if (Local_System_Name[0] != 0)
-               memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
-       else {
-               char *nodename = utsname()->nodename;
-               int n = strnlen(nodename, 15);
-               memset(vol->source_rfc1001_name, 0x20, 15);
-               for (i = 0; i < n; i++) {
-                       /* does not have to be perfect mapping since field is
-                       informational, only used for servers that do not support
-                       port 445 and it can be overridden at mount time */
-                       vol->source_rfc1001_name[i] = toupper(nodename[i]);
-               }
-       }
+       /*
+        * does not have to be perfect mapping since field is
+        * informational, only used for servers that do not support
+        * port 445 and it can be overridden at mount time
+        */
+       memset(vol->source_rfc1001_name, 0x20, 15);
+       for (i = 0; i < strnlen(nodename, 15); i++)
+               vol->source_rfc1001_name[i] = toupper(nodename[i]);
+
        vol->source_rfc1001_name[15] = 0;
        /* null target name indicates to use *SMBSERVR default called name
           if we end up sending RFC1001 session initialize */
@@ -840,6 +838,8 @@ cifs_parse_mount_options(char *options, const char *devname,
        /* default to using server inode numbers where available */
        vol->server_ino = 1;
 
+       vol->actimeo = CIFS_DEF_ACTIMEO;
+
        if (!options)
                return 1;
 
@@ -1214,6 +1214,16 @@ cifs_parse_mount_options(char *options, const char *devname,
                                        printk(KERN_WARNING "CIFS: server net"
                                        "biosname longer than 15 truncated.\n");
                        }
+               } else if (strnicmp(data, "actimeo", 7) == 0) {
+                       if (value && *value) {
+                               vol->actimeo = HZ * simple_strtoul(value,
+                                                                  &value, 0);
+                               if (vol->actimeo > CIFS_MAX_ACTIMEO) {
+                                       cERROR(1, "CIFS: attribute cache"
+                                                       "timeout too large");
+                                       return 1;
+                               }
+                       }
                } else if (strnicmp(data, "credentials", 4) == 0) {
                        /* ignore */
                } else if (strnicmp(data, "version", 3) == 0) {
@@ -2571,6 +2581,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
        cFYI(1, "file mode: 0x%x  dir mode: 0x%x",
                cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
 
+       cifs_sb->actimeo = pvolume_info->actimeo;
+
        if (pvolume_info->noperm)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
        if (pvolume_info->setuids)
@@ -2821,13 +2833,13 @@ remote_path_check:
        /* check if a whole path (including prepath) is not remote */
        if (!rc && cifs_sb->prepathlen && tcon) {
                /* build_path_to_root works only when we have a valid tcon */
-               full_path = cifs_build_path_to_root(cifs_sb);
+               full_path = cifs_build_path_to_root(cifs_sb, tcon);
                if (full_path == NULL) {
                        rc = -ENOMEM;
                        goto mount_fail_check;
                }
                rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
-               if (rc != -EREMOTE) {
+               if (rc != 0 && rc != -EREMOTE) {
                        kfree(full_path);
                        goto mount_fail_check;
                }
index b857ce5db7755143affed1224c778d34ddc77b99..5a28660ca2b5e619955c05d74d9d84b95a994a4b 100644 (file)
@@ -1108,7 +1108,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
        return total_written;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
 {
@@ -1142,7 +1141,6 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
        spin_unlock(&cifs_file_list_lock);
        return NULL;
 }
-#endif
 
 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
index 28cb6e735943f935d3ed9408f34152ba35f100b7..589f3e3f6e0023b1f8b09f1e030119896117c94f 100644 (file)
@@ -686,7 +686,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        cFYI(1, "cifs_sfu_type failed: %d", tmprc);
        }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
        /* fill in 0777 bits from ACL */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
@@ -697,7 +697,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        goto cgii_exit;
                }
        }
-#endif
+#endif /* CONFIG_CIFS_ACL */
 
        /* fill in remaining high mode bits e.g. SUID, VTX */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
@@ -728,12 +728,12 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
-char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
+char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                               struct cifsTconInfo *tcon)
 {
        int pplen = cifs_sb->prepathlen;
        int dfsplen;
        char *full_path = NULL;
-       struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
        /* if no prefix path, simply set path to the root of share to "" */
        if (pplen == 0) {
@@ -875,7 +875,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
        char *full_path;
        struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
-       full_path = cifs_build_path_to_root(cifs_sb);
+       full_path = cifs_build_path_to_root(cifs_sb, tcon);
        if (full_path == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -1653,6 +1653,7 @@ static bool
 cifs_inode_needs_reval(struct inode *inode)
 {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
        if (cifs_i->clientCanCacheRead)
                return false;
@@ -1663,12 +1664,12 @@ cifs_inode_needs_reval(struct inode *inode)
        if (cifs_i->time == 0)
                return true;
 
-       /* FIXME: the actimeo should be tunable */
-       if (time_after_eq(jiffies, cifs_i->time + HZ))
+       if (!time_in_range(jiffies, cifs_i->time,
+                               cifs_i->time + cifs_sb->actimeo))
                return true;
 
        /* hardlinked files w/ noserverino get "special" treatment */
-       if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
            S_ISREG(inode->i_mode) && inode->i_nlink != 1)
                return true;
 
@@ -2121,7 +2122,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
        if (attrs->ia_valid & ATTR_MODE) {
                rc = 0;
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                        rc = mode_to_cifs_acl(inode, full_path, mode);
                        if (rc) {
@@ -2130,7 +2131,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                                goto cifs_setattr_exit;
                        }
                } else
-#endif
+#endif /* CONFIG_CIFS_ACL */
                if (((mode & S_IWUGO) == 0) &&
                    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
 
index 32d300e8f20eb4a6676b8da50187a4b04146fcb8..a73eb9f4bdaf3608c2bf6f5dc124b5fabdd4445b 100644 (file)
@@ -759,18 +759,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
        rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
                     ino, fattr.cf_dtype);
 
-       /*
-        * we can not return filldir errors to the caller since they are
-        * "normal" when the stat blocksize is too small - we return remapped
-        * error instead
-        *
-        * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
-        * case already. Why should we be clobbering other errors from it?
-        */
-       if (rc) {
-               cFYI(1, "filldir rc = %d", rc);
-               rc = -EOVERFLOW;
-       }
        dput(tmp_dentry);
        return rc;
 }
index d68c378a31375bfb848aaa887fb655a8b08ec080..c62efcb959c73fc458367d811c576e634fb49634 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -275,6 +275,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
        vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
        vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
        INIT_LIST_HEAD(&vma->anon_vma_chain);
+
+       err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+       if (err)
+               goto err;
+
        err = insert_vm_struct(mm, vma);
        if (err)
                goto err;
index 6a5edea2d70b3ac7c56e8b272686b5a799eabbcf..94ce3d7a1c4b9fe83b42954d309c8ac93b284ff5 100644 (file)
@@ -910,6 +910,7 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_JOURNAL_CHECKSUM    0x800000 /* Journal checksums */
 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT        0x1000000 /* Journal Async Commit */
 #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
+#define EXT4_MOUNT_MBLK_IO_SUBMIT      0x4000000 /* multi-block io submits */
 #define EXT4_MOUNT_DELALLOC            0x8000000 /* Delalloc support */
 #define EXT4_MOUNT_DATA_ERR_ABORT      0x10000000 /* Abort on file data write */
 #define EXT4_MOUNT_BLOCK_VALIDITY      0x20000000 /* Block validity checking */
index bdbe69902207c151df025d98690c4c016cf0b0e9..e659597b690b508e1325182de702031a73843f4d 100644 (file)
@@ -2125,9 +2125,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
                         */
                        if (unlikely(journal_data && PageChecked(page)))
                                err = __ext4_journalled_writepage(page, len);
-                       else
+                       else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
                                err = ext4_bio_write_page(&io_submit, page,
                                                          len, mpd->wbc);
+                       else
+                               err = block_write_full_page(page,
+                                       noalloc_get_block_write, mpd->wbc);
 
                        if (!err)
                                mpd->pages_written++;
index 92203b8a099f076ebbc0d794b3356289096c663f..dc40e75cba8857e6068739646b4932bb315688fd 100644 (file)
@@ -872,7 +872,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
        if (namelen > EXT4_NAME_LEN)
                return NULL;
        if ((namelen <= 2) && (name[0] == '.') &&
-           (name[1] == '.' || name[1] == '0')) {
+           (name[1] == '.' || name[1] == '\0')) {
                /*
                 * "." or ".." will only be in the first block
                 * NFS may look up ".."; "." should be handled by the VFS
index e32195d6aac34656b13a5619c3750e8b30586c08..fb15c9c0be74d5c06ba421f04449d981a69337ed 100644 (file)
@@ -1026,6 +1026,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
            !(def_mount_opts & EXT4_DEFM_NODELALLOC))
                seq_puts(seq, ",nodelalloc");
 
+       if (test_opt(sb, MBLK_IO_SUBMIT))
+               seq_puts(seq, ",mblk_io_submit");
        if (sbi->s_stripe)
                seq_printf(seq, ",stripe=%lu", sbi->s_stripe);
        /*
@@ -1239,8 +1241,8 @@ enum {
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
        Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
        Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version,
-       Opt_stripe, Opt_delalloc, Opt_nodelalloc,
-       Opt_block_validity, Opt_noblock_validity,
+       Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit,
+       Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
        Opt_inode_readahead_blks, Opt_journal_ioprio,
        Opt_dioread_nolock, Opt_dioread_lock,
        Opt_discard, Opt_nodiscard,
@@ -1304,6 +1306,8 @@ static const match_table_t tokens = {
        {Opt_resize, "resize"},
        {Opt_delalloc, "delalloc"},
        {Opt_nodelalloc, "nodelalloc"},
+       {Opt_mblk_io_submit, "mblk_io_submit"},
+       {Opt_nomblk_io_submit, "nomblk_io_submit"},
        {Opt_block_validity, "block_validity"},
        {Opt_noblock_validity, "noblock_validity"},
        {Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
@@ -1725,6 +1729,12 @@ set_qf_format:
                case Opt_nodelalloc:
                        clear_opt(sbi->s_mount_opt, DELALLOC);
                        break;
+               case Opt_mblk_io_submit:
+                       set_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
+                       break;
+               case Opt_nomblk_io_submit:
+                       clear_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT);
+                       break;
                case Opt_stripe:
                        if (match_int(&args[0], &option))
                                return 0;
index 9242d294fe90d382fb7a40f1220923baea71c97e..8b984a2cebbda185af01a6d4d5f8c31c89fc6fbe 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/compat.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -1627,6 +1628,58 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
        return 0;
 }
 
+/*
+ * CUSE servers compiled on 32bit broke on 64bit kernels because the
+ * ABI was defined to be 'struct iovec' which is different on 32bit
+ * and 64bit.  Fortunately we can determine which structure the server
+ * used from the size of the reply.
+ */
+static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src,
+                                size_t transferred, unsigned count,
+                                bool is_compat)
+{
+#ifdef CONFIG_COMPAT
+       if (count * sizeof(struct compat_iovec) == transferred) {
+               struct compat_iovec *ciov = src;
+               unsigned i;
+
+               /*
+                * With this interface a 32bit server cannot support
+                * non-compat (i.e. ones coming from 64bit apps) ioctl
+                * requests
+                */
+               if (!is_compat)
+                       return -EINVAL;
+
+               for (i = 0; i < count; i++) {
+                       dst[i].iov_base = compat_ptr(ciov[i].iov_base);
+                       dst[i].iov_len = ciov[i].iov_len;
+               }
+               return 0;
+       }
+#endif
+
+       if (count * sizeof(struct iovec) != transferred)
+               return -EIO;
+
+       memcpy(dst, src, transferred);
+       return 0;
+}
+
+/* Make sure iov_length() won't overflow */
+static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
+{
+       size_t n;
+       u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
+
+       for (n = 0; n < count; n++) {
+               if (iov->iov_len > (size_t) max)
+                       return -ENOMEM;
+               max -= iov->iov_len;
+       }
+       return 0;
+}
+
 /*
  * For ioctls, there is no generic way to determine how much memory
  * needs to be read and/or written.  Furthermore, ioctls are allowed
@@ -1808,18 +1861,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
                        goto out;
 
-               err = -EIO;
-               if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred)
-                       goto out;
-
-               /* okay, copy in iovs and retry */
                vaddr = kmap_atomic(pages[0], KM_USER0);
-               memcpy(page_address(iov_page), vaddr, transferred);
+               err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr,
+                                           transferred, in_iovs + out_iovs,
+                                           (flags & FUSE_IOCTL_COMPAT) != 0);
                kunmap_atomic(vaddr, KM_USER0);
+               if (err)
+                       goto out;
 
                in_iov = page_address(iov_page);
                out_iov = in_iov + in_iovs;
 
+               err = fuse_verify_ioctl_iov(in_iov, in_iovs);
+               if (err)
+                       goto out;
+
+               err = fuse_verify_ioctl_iov(out_iov, out_iovs);
+               if (err)
+                       goto out;
+
                goto retry;
        }
 
index f0a384e2ae633a1dc2de619d102d5935ff32a273..996dd8989a9135203cab110f57e7c1f8df49e200 100644 (file)
@@ -57,7 +57,7 @@ static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
-static int nfs_readdir_clear_array(struct page*, gfp_t);
+static void nfs_readdir_clear_array(struct page*);
 
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
@@ -83,8 +83,8 @@ const struct inode_operations nfs_dir_inode_operations = {
        .setattr        = nfs_setattr,
 };
 
-const struct address_space_operations nfs_dir_addr_space_ops = {
-       .releasepage = nfs_readdir_clear_array,
+const struct address_space_operations nfs_dir_aops = {
+       .freepage = nfs_readdir_clear_array,
 };
 
 #ifdef CONFIG_NFS_V3
@@ -178,6 +178,7 @@ typedef struct {
        struct page     *page;
        unsigned long   page_index;
        u64             *dir_cookie;
+       u64             last_cookie;
        loff_t          current_index;
        decode_dirent_t decode;
 
@@ -213,17 +214,15 @@ void nfs_readdir_release_array(struct page *page)
  * we are freeing strings created by nfs_add_to_readdir_array()
  */
 static
-int nfs_readdir_clear_array(struct page *page, gfp_t mask)
+void nfs_readdir_clear_array(struct page *page)
 {
-       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       struct nfs_cache_array *array;
        int i;
 
-       if (IS_ERR(array))
-               return PTR_ERR(array);
+       array = kmap_atomic(page, KM_USER0);
        for (i = 0; i < array->size; i++)
                kfree(array->array[i].string.name);
-       nfs_readdir_release_array(page);
-       return 0;
+       kunmap_atomic(array, KM_USER0);
 }
 
 /*
@@ -272,7 +271,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
                goto out;
        array->last_cookie = entry->cookie;
        array->size++;
-       if (entry->eof == 1)
+       if (entry->eof != 0)
                array->eof_index = array->size;
 out:
        nfs_readdir_release_array(page);
@@ -312,15 +311,14 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
        for (i = 0; i < array->size; i++) {
                if (array->array[i].cookie == *desc->dir_cookie) {
                        desc->cache_entry_index = i;
-                       status = 0;
-                       goto out;
+                       return 0;
                }
        }
-       if (i == array->eof_index) {
-               desc->eof = 1;
+       if (array->eof_index >= 0) {
                status = -EBADCOOKIE;
+               if (*desc->dir_cookie == array->last_cookie)
+                       desc->eof = 1;
        }
-out:
        return status;
 }
 
@@ -328,10 +326,7 @@ static
 int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
 {
        struct nfs_cache_array *array;
-       int status = -EBADCOOKIE;
-
-       if (desc->dir_cookie == NULL)
-               goto out;
+       int status;
 
        array = nfs_readdir_get_array(desc->page);
        if (IS_ERR(array)) {
@@ -344,6 +339,10 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
        else
                status = nfs_readdir_search_for_cookie(array, desc);
 
+       if (status == -EAGAIN) {
+               desc->last_cookie = array->last_cookie;
+               desc->page_index++;
+       }
        nfs_readdir_release_array(desc->page);
 out:
        return status;
@@ -490,7 +489,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
 
                count++;
 
-               if (desc->plus == 1)
+               if (desc->plus != 0)
                        nfs_prime_dcache(desc->file->f_path.dentry, entry);
 
                status = nfs_readdir_add_to_array(entry, page);
@@ -498,7 +497,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
        } while (!entry->eof);
 
-       if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) {
+       if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
                array = nfs_readdir_get_array(page);
                if (!IS_ERR(array)) {
                        array->eof_index = array->size;
@@ -563,7 +562,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
        unsigned int array_size = ARRAY_SIZE(pages);
 
        entry.prev_cookie = 0;
-       entry.cookie = *desc->dir_cookie;
+       entry.cookie = desc->last_cookie;
        entry.eof = 0;
        entry.fh = nfs_alloc_fhandle();
        entry.fattr = nfs_alloc_fattr();
@@ -636,6 +635,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 static
 void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
+       if (!desc->page->mapping)
+               nfs_readdir_clear_array(desc->page);
        page_cache_release(desc->page);
        desc->page = NULL;
 }
@@ -660,9 +661,8 @@ int find_cache_page(nfs_readdir_descriptor_t *desc)
                return PTR_ERR(desc->page);
 
        res = nfs_readdir_search_array(desc);
-       if (res == 0)
-               return 0;
-       cache_page_release(desc);
+       if (res != 0)
+               cache_page_release(desc);
        return res;
 }
 
@@ -672,22 +672,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
        int res;
 
-       if (desc->page_index == 0)
+       if (desc->page_index == 0) {
                desc->current_index = 0;
-       while (1) {
-               res = find_cache_page(desc);
-               if (res != -EAGAIN)
-                       break;
-               desc->page_index++;
+               desc->last_cookie = 0;
        }
+       do {
+               res = find_cache_page(desc);
+       } while (res == -EAGAIN);
        return res;
 }
 
-static inline unsigned int dt_type(struct inode *inode)
-{
-       return (inode->i_mode >> 12) & 15;
-}
-
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -717,13 +711,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                        break;
                }
                file->f_pos++;
-               desc->cache_entry_index = i;
                if (i < (array->size-1))
                        *desc->dir_cookie = array->array[i+1].cookie;
                else
                        *desc->dir_cookie = array->last_cookie;
        }
-       if (i == array->eof_index)
+       if (array->eof_index >= 0)
                desc->eof = 1;
 
        nfs_readdir_release_array(desc->page);
@@ -764,6 +757,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        }
 
        desc->page_index = 0;
+       desc->last_cookie = *desc->dir_cookie;
        desc->page = page;
 
        status = nfs_readdir_xdr_to_array(desc, page, inode);
@@ -791,7 +785,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
-       int res = -ENOMEM;
+       int res;
 
        dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -816,7 +810,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if (res < 0)
                goto out;
 
-       while (desc->eof != 1) {
+       do {
                res = readdir_search_pagecache(desc);
 
                if (res == -EBADCOOKIE) {
@@ -844,7 +838,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                res = nfs_do_filldir(desc, dirent, filldir);
                if (res < 0)
                        break;
-       }
+       } while (!desc->eof);
 out:
        nfs_unblock_sillyrename(dentry);
        if (res > 0)
index 60677f9f13110d1a98774595de819fddf2c0ccdf..7bf029ef4084c6e7f02e05e355382168e85e2cb8 100644 (file)
@@ -693,6 +693,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
+       unsigned int saved_type = fl->fl_type;
 
        /* Try local locking first */
        posix_test_lock(filp, fl);
@@ -700,6 +701,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
                /* found a conflict */
                goto out;
        }
+       fl->fl_type = saved_type;
 
        if (nfs_have_delegation(inode, FMODE_READ))
                goto out_noconflict;
index 314f57164602eda0762c0a226db44aa19be461f5..e67e31c734163c6fe6c0eef0d338a2b87ae55763 100644 (file)
@@ -289,6 +289,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                } else if (S_ISDIR(inode->i_mode)) {
                        inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
                        inode->i_fop = &nfs_dir_operations;
+                       inode->i_data.a_ops = &nfs_dir_aops;
                        if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
                                set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        /* Deal with crossing mountpoints */
index eceafe74f4737ea5fbcea90b8ac19749737667b9..4f981f1f668925cba6bebe6ed4cf485da6a56dbb 100644 (file)
@@ -505,13 +505,13 @@ static struct rpc_procinfo mnt3_procedures[] = {
 
 static struct rpc_version mnt_version1 = {
        .number         = 1,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt_procedures),
        .procs          = mnt_procedures,
 };
 
 static struct rpc_version mnt_version3 = {
        .number         = 3,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt3_procedures),
        .procs          = mnt3_procedures,
 };
 
index 6a653ffd8e4e121e37c29d88ff2f5b0b4dbe264f..4435e5e1f904e3e5ba26f4eb578fc30c5f6d997b 100644 (file)
@@ -3361,6 +3361,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
        ret = nfs_revalidate_inode(server, inode);
        if (ret < 0)
                return ret;
+       if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
+               nfs_zap_acl_cache(inode);
        ret = nfs4_read_cached_acl(inode, buf, buflen);
        if (ret != -ENOENT)
                return ret;
@@ -3389,6 +3391,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
        nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
+       /*
+        * Acl update can result in inode attribute update.
+        * so mark the attribute cache invalid.
+        */
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
+       spin_unlock(&inode->i_lock);
        nfs_access_zap_cache(inode);
        nfs_zap_acl_cache(inode);
        return ret;
index 137b549e63dbcfa3971aac43091eb91a29a7b69f..b68536cc9046ec937b9b4ccddb98b2acf468f1db 100644 (file)
@@ -115,7 +115,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
 {
        if (!nfs_lock_request_dontget(req))
                return 0;
-       if (req->wb_page != NULL)
+       if (test_bit(PG_MAPPED, &req->wb_flags))
                radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
        return 1;
 }
@@ -125,7 +125,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
  */
 void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
-       if (req->wb_page != NULL) {
+       if (test_bit(PG_MAPPED, &req->wb_flags)) {
                struct inode *inode = req->wb_context->path.dentry->d_inode;
                struct nfs_inode *nfsi = NFS_I(inode);
 
index e4b62c6f5a6e9eb721eda53d836c41055ab2e1b7..aedcaa7f291fbe4405f2b68c13f407c7de6be9ba 100644 (file)
@@ -152,7 +152,6 @@ static void nfs_readpage_release(struct nfs_page *req)
                        (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 3c045044fca25183147704f3689c744549ebd77b..4100630c9a5b65f47bb5379ee2bc62f78e60284e 100644 (file)
@@ -1069,12 +1069,10 @@ static int nfs_parse_mount_options(char *raw,
                        mnt->flags |= NFS_MOUNT_VER3;
                        mnt->version = 3;
                        break;
-#ifdef CONFIG_NFS_V4
                case Opt_v4:
                        mnt->flags &= ~NFS_MOUNT_VER3;
                        mnt->version = 4;
                        break;
-#endif
                case Opt_udp:
                        mnt->flags &= ~NFS_MOUNT_TCP;
                        mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
@@ -1286,12 +1284,10 @@ static int nfs_parse_mount_options(char *raw,
                                mnt->flags |= NFS_MOUNT_VER3;
                                mnt->version = 3;
                                break;
-#ifdef CONFIG_NFS_V4
                        case NFS4_VERSION:
                                mnt->flags &= ~NFS_MOUNT_VER3;
                                mnt->version = 4;
                                break;
-#endif
                        default:
                                goto out_invalid_value;
                        }
index 4c14c17a5276a410bb383e3650f106ab56cf47d6..10d648ea128bf6345df70da0e15ee8ce443ab8e6 100644 (file)
@@ -390,6 +390,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
                if (nfs_have_delegation(inode, FMODE_WRITE))
                        nfsi->change_attr++;
        }
+       set_bit(PG_MAPPED, &req->wb_flags);
        SetPagePrivate(req->wb_page);
        set_page_private(req->wb_page, (unsigned long)req);
        nfsi->npages++;
@@ -415,6 +416,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        spin_lock(&inode->i_lock);
        set_page_private(req->wb_page, 0);
        ClearPagePrivate(req->wb_page);
+       clear_bit(PG_MAPPED, &req->wb_flags);
        radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
        nfsi->npages--;
        if (!nfsi->npages) {
@@ -422,7 +424,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
                iput(inode);
        } else
                spin_unlock(&inode->i_lock);
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 2a533a0af2a98ed91afb84e71669d328cb67a866..7e84a852cdae8117334fec6ee00d085fc29c0c66 100644 (file)
@@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp)
        err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
                        &fhp->fh_post_attr);
        fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
-       if (err)
+       if (err) {
                fhp->fh_post_saved = 0;
-       else
+               /* Grab the ctime anyway - set_change_info might use it */
+               fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
+       } else
                fhp->fh_post_saved = 1;
 }
 
index 4d476ff08ae6add1ec3a1b597909f1375af78b7b..60fce3dc5cb5d9f90d22b9f9c91ddc7ddeb9ff1d 100644 (file)
@@ -484,18 +484,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
 static inline void
 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
-       BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
-       cinfo->atomic = 1;
+       BUG_ON(!fhp->fh_pre_saved);
+       cinfo->atomic = fhp->fh_post_saved;
        cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
-       if (cinfo->change_supported) {
-               cinfo->before_change = fhp->fh_pre_change;
-               cinfo->after_change = fhp->fh_post_change;
-       } else {
-               cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
-               cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
-               cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
-               cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
-       }
+
+       cinfo->before_change = fhp->fh_pre_change;
+       cinfo->after_change = fhp->fh_post_change;
+       cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+       cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+       cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
+       cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
+
 }
 
 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
index d2af0a8381a63975e9668d1aa7babb942bd4f4e2..77a59891734e925318f4a91723f96eb55f7b5ae8 100644 (file)
@@ -297,6 +297,7 @@ xfs_rename(
         * it and some incremental backup programs won't work without it.
         */
        xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG);
+       xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE);
 
        /*
         * Adjust the link count on src_dp.  This is necessary when
index 551793c9b6e8c25b2b1d3e36a4fe8ffcb4a0f24a..0e98e679d3a749cfda3898c2fe59f82d18ca87c3 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __ACPI_VIDEO_H
 #define __ACPI_VIDEO_H
 
+#include <linux/errno.h> /* for ENODEV */
+
+struct acpi_device;
+
 #define ACPI_VIDEO_DISPLAY_CRT  1
 #define ACPI_VIDEO_DISPLAY_TV   2
 #define ACPI_VIDEO_DISPLAY_DVI  3
@@ -26,4 +30,3 @@ static inline int acpi_video_get_edid(struct acpi_device *device, int type,
 #endif
 
 #endif
-
index 8c641bed9bbd36526870b6741fdd16f780e3b0ec..a2776e2807a4ce39051df02b7384da32d58c1545 100644 (file)
@@ -287,6 +287,8 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_EXECBUF2          9
 #define I915_PARAM_HAS_BSD              10
 #define I915_PARAM_HAS_BLT              11
+#define I915_PARAM_HAS_RELAXED_FENCING  12
+#define I915_PARAM_HAS_COHERENT_RINGS   13
 
 typedef struct drm_i915_getparam {
        int param;
index 050a7bccb8365ef117f365ebe3d3a8d337efc390..67c91b4418b06e59ea9de82e0c67dfb4cc5a7554 100644 (file)
@@ -219,7 +219,7 @@ static inline int acpi_video_display_switch_support(void)
 
 extern int acpi_blacklisted(void);
 extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
-extern int acpi_osi_setup(char *str);
+extern void acpi_osi_setup(char *str);
 
 #ifdef CONFIG_ACPI_NUMA
 int acpi_get_pxm(acpi_handle handle);
index a8e4e832cdbb094d8a99ad9d831db3d14cbdbe23..475f8c42c0e928b57fbaf370bb89471642391b77 100644 (file)
@@ -427,8 +427,10 @@ extern rwlock_t vcc_sklist_lock;
 
 #define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
 
-struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
-    int number,unsigned long *flags); /* number == -1: pick first available */
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+                                const struct atmdev_ops *ops,
+                                int number, /* -1 == pick first available */
+                                unsigned long *flags);
 struct atm_dev *atm_dev_lookup(int number);
 void atm_dev_deregister(struct atm_dev *dev);
 
index c9e06cc70dad585c6c185db2d1503d3fad4a5a48..090f0eacde296ec52a06fe5eb1b13c07808b7ada 100644 (file)
@@ -602,6 +602,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        void (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, gfp_t);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*get_xip_mem)(struct address_space *, pgoff_t, int,
index ce73a30113b4d0181ef7a2131c060ca18f1de027..dd1a56fbe9241235f4baa059394d5d36bd050de7 100644 (file)
@@ -16,6 +16,8 @@ struct gpio_keys_button {
 struct gpio_keys_platform_data {
        struct gpio_keys_button *buttons;
        int nbuttons;
+       unsigned int poll_interval;     /* polling interval in msecs -
+                                          for polling driver only */
        unsigned int rep:1;             /* enable input subsystem auto repeat */
        int (*enable)(struct device *dev);
        void (*disable)(struct device *dev);
index 6ef44465db8ddc31c41be1de00eeef38c53b5fa5..a8af21d42bc146cc6f6ee186894e623b01a884ff 100644 (file)
@@ -47,6 +47,25 @@ struct input_id {
        __u16 version;
 };
 
+/**
+ * struct input_absinfo - used by EVIOCGABS/EVIOCSABS ioctls
+ * @value: latest reported value for the axis.
+ * @minimum: specifies minimum value for the axis.
+ * @maximum: specifies maximum value for the axis.
+ * @fuzz: specifies fuzz value that is used to filter noise from
+ *     the event stream.
+ * @flat: values that are within this value will be discarded by
+ *     joydev interface and reported as 0 instead.
+ * @resolution: specifies resolution for the values reported for
+ *     the axis.
+ *
+ * Note that input core does not clamp reported values to the
+ * [minimum, maximum] limits, such task is left to userspace.
+ *
+ * Resolution for main axes (ABS_X, ABS_Y, ABS_Z) is reported in
+ * units per millimeter (units/mm), resolution for rotational axes
+ * (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian.
+ */
 struct input_absinfo {
        __s32 value;
        __s32 minimum;
@@ -624,6 +643,10 @@ struct input_keymap_entry {
 #define KEY_CAMERA_FOCUS       0x210
 #define KEY_WPS_BUTTON         0x211   /* WiFi Protected Setup key */
 
+#define KEY_TOUCHPAD_TOGGLE    0x212   /* Request switch touchpad on or off */
+#define KEY_TOUCHPAD_ON                0x213
+#define KEY_TOUCHPAD_OFF       0x214
+
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
 #define BTN_TRIGGER_HAPPY2             0x2c1
@@ -1130,7 +1153,7 @@ struct input_mt_slot {
  *     of tracked contacts
  * @mtsize: number of MT slots the device uses
  * @slot: MT slot currently being transmitted
- * @absinfo: array of &struct absinfo elements holding information
+ * @absinfo: array of &struct input_absinfo elements holding information
  *     about absolute axes (current value, min, max, flat, fuzz,
  *     resolution)
  * @key: reflects current state of device's keys/buttons
diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h
deleted file mode 100644 (file)
index eff3094..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- */
-
-#ifndef __LINUX_MFD_TC35892_H
-#define __LINUX_MFD_TC35892_H
-
-#include <linux/device.h>
-
-#define TC35892_RSTCTRL_IRQRST (1 << 4)
-#define TC35892_RSTCTRL_TIMRST (1 << 3)
-#define TC35892_RSTCTRL_ROTRST (1 << 2)
-#define TC35892_RSTCTRL_KBDRST (1 << 1)
-#define TC35892_RSTCTRL_GPIRST (1 << 0)
-
-#define TC35892_IRQST          0x91
-
-#define TC35892_MANFCODE_MAGIC 0x03
-#define TC35892_MANFCODE       0x80
-#define TC35892_VERSION                0x81
-#define TC35892_IOCFG          0xA7
-
-#define TC35892_CLKMODE                0x88
-#define TC35892_CLKCFG         0x89
-#define TC35892_CLKEN          0x8A
-
-#define TC35892_RSTCTRL                0x82
-#define TC35892_EXTRSTN                0x83
-#define TC35892_RSTINTCLR      0x84
-
-#define TC35892_GPIOIS0                0xC9
-#define TC35892_GPIOIS1                0xCA
-#define TC35892_GPIOIS2                0xCB
-#define TC35892_GPIOIBE0       0xCC
-#define TC35892_GPIOIBE1       0xCD
-#define TC35892_GPIOIBE2       0xCE
-#define TC35892_GPIOIEV0       0xCF
-#define TC35892_GPIOIEV1       0xD0
-#define TC35892_GPIOIEV2       0xD1
-#define TC35892_GPIOIE0                0xD2
-#define TC35892_GPIOIE1                0xD3
-#define TC35892_GPIOIE2                0xD4
-#define TC35892_GPIORIS0       0xD6
-#define TC35892_GPIORIS1       0xD7
-#define TC35892_GPIORIS2       0xD8
-#define TC35892_GPIOMIS0       0xD9
-#define TC35892_GPIOMIS1       0xDA
-#define TC35892_GPIOMIS2       0xDB
-#define TC35892_GPIOIC0                0xDC
-#define TC35892_GPIOIC1                0xDD
-#define TC35892_GPIOIC2                0xDE
-
-#define TC35892_GPIODATA0      0xC0
-#define TC35892_GPIOMASK0      0xc1
-#define TC35892_GPIODATA1      0xC2
-#define TC35892_GPIOMASK1      0xc3
-#define TC35892_GPIODATA2      0xC4
-#define TC35892_GPIOMASK2      0xC5
-
-#define TC35892_GPIODIR0       0xC6
-#define TC35892_GPIODIR1       0xC7
-#define TC35892_GPIODIR2       0xC8
-
-#define TC35892_GPIOSYNC0      0xE6
-#define TC35892_GPIOSYNC1      0xE7
-#define TC35892_GPIOSYNC2      0xE8
-
-#define TC35892_GPIOWAKE0      0xE9
-#define TC35892_GPIOWAKE1      0xEA
-#define TC35892_GPIOWAKE2      0xEB
-
-#define TC35892_GPIOODM0       0xE0
-#define TC35892_GPIOODE0       0xE1
-#define TC35892_GPIOODM1       0xE2
-#define TC35892_GPIOODE1       0xE3
-#define TC35892_GPIOODM2       0xE4
-#define TC35892_GPIOODE2       0xE5
-
-#define TC35892_INT_GPIIRQ     0
-#define TC35892_INT_TI0IRQ     1
-#define TC35892_INT_TI1IRQ     2
-#define TC35892_INT_TI2IRQ     3
-#define TC35892_INT_ROTIRQ     5
-#define TC35892_INT_KBDIRQ     6
-#define TC35892_INT_PORIRQ     7
-
-#define TC35892_NR_INTERNAL_IRQS       8
-#define TC35892_INT_GPIO(x)    (TC35892_NR_INTERNAL_IRQS + (x))
-
-struct tc35892 {
-       struct mutex lock;
-       struct device *dev;
-       struct i2c_client *i2c;
-
-       int irq_base;
-       int num_gpio;
-       struct tc35892_platform_data *pdata;
-};
-
-extern int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data);
-extern int tc35892_reg_read(struct tc35892 *tc35892, u8 reg);
-extern int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length,
-                             u8 *values);
-extern int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
-                              const u8 *values);
-extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val);
-
-/**
- * struct tc35892_gpio_platform_data - TC35892 GPIO platform data
- * @gpio_base: first gpio number assigned to TC35892.  A maximum of
- *            %TC35892_NR_GPIOS GPIOs will be allocated.
- * @setup: callback for board-specific initialization
- * @remove: callback for board-specific teardown
- */
-struct tc35892_gpio_platform_data {
-       int gpio_base;
-       void (*setup)(struct tc35892 *tc35892, unsigned gpio_base);
-       void (*remove)(struct tc35892 *tc35892, unsigned gpio_base);
-};
-
-/**
- * struct tc35892_platform_data - TC35892 platform data
- * @irq_base: base IRQ number.  %TC35892_NR_IRQS irqs will be used.
- * @gpio: GPIO-specific platform data
- */
-struct tc35892_platform_data {
-       int irq_base;
-       struct tc35892_gpio_platform_data *gpio;
-};
-
-#define TC35892_NR_GPIOS       24
-#define TC35892_NR_IRQS                TC35892_INT_GPIO(TC35892_NR_GPIOS)
-
-#endif
diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h
new file mode 100644 (file)
index 0000000..16c76e1
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ */
+
+#ifndef __LINUX_MFD_TC3589x_H
+#define __LINUX_MFD_TC3589x_H
+
+#include <linux/device.h>
+
+enum tx3589x_block {
+       TC3589x_BLOCK_GPIO        = 1 << 0,
+       TC3589x_BLOCK_KEYPAD      = 1 << 1,
+};
+
+#define TC3589x_RSTCTRL_IRQRST (1 << 4)
+#define TC3589x_RSTCTRL_TIMRST (1 << 3)
+#define TC3589x_RSTCTRL_ROTRST (1 << 2)
+#define TC3589x_RSTCTRL_KBDRST (1 << 1)
+#define TC3589x_RSTCTRL_GPIRST (1 << 0)
+
+/* Keyboard Configuration Registers */
+#define TC3589x_KBDSETTLE_REG   0x01
+#define TC3589x_KBDBOUNCE       0x02
+#define TC3589x_KBDSIZE         0x03
+#define TC3589x_KBCFG_LSB       0x04
+#define TC3589x_KBCFG_MSB       0x05
+#define TC3589x_KBDIC           0x08
+#define TC3589x_KBDMSK          0x09
+#define TC3589x_EVTCODE_FIFO    0x10
+#define TC3589x_KBDMFS         0x8F
+
+#define TC3589x_IRQST          0x91
+
+#define TC3589x_MANFCODE_MAGIC 0x03
+#define TC3589x_MANFCODE       0x80
+#define TC3589x_VERSION                0x81
+#define TC3589x_IOCFG          0xA7
+
+#define TC3589x_CLKMODE                0x88
+#define TC3589x_CLKCFG         0x89
+#define TC3589x_CLKEN          0x8A
+
+#define TC3589x_RSTCTRL                0x82
+#define TC3589x_EXTRSTN                0x83
+#define TC3589x_RSTINTCLR      0x84
+
+/* Pull up/down configuration registers */
+#define TC3589x_IOCFG           0xA7
+#define TC3589x_IOPULLCFG0_LSB  0xAA
+#define TC3589x_IOPULLCFG0_MSB  0xAB
+#define TC3589x_IOPULLCFG1_LSB  0xAC
+#define TC3589x_IOPULLCFG1_MSB  0xAD
+#define TC3589x_IOPULLCFG2_LSB  0xAE
+
+#define TC3589x_GPIOIS0                0xC9
+#define TC3589x_GPIOIS1                0xCA
+#define TC3589x_GPIOIS2                0xCB
+#define TC3589x_GPIOIBE0       0xCC
+#define TC3589x_GPIOIBE1       0xCD
+#define TC3589x_GPIOIBE2       0xCE
+#define TC3589x_GPIOIEV0       0xCF
+#define TC3589x_GPIOIEV1       0xD0
+#define TC3589x_GPIOIEV2       0xD1
+#define TC3589x_GPIOIE0                0xD2
+#define TC3589x_GPIOIE1                0xD3
+#define TC3589x_GPIOIE2                0xD4
+#define TC3589x_GPIORIS0       0xD6
+#define TC3589x_GPIORIS1       0xD7
+#define TC3589x_GPIORIS2       0xD8
+#define TC3589x_GPIOMIS0       0xD9
+#define TC3589x_GPIOMIS1       0xDA
+#define TC3589x_GPIOMIS2       0xDB
+#define TC3589x_GPIOIC0                0xDC
+#define TC3589x_GPIOIC1                0xDD
+#define TC3589x_GPIOIC2                0xDE
+
+#define TC3589x_GPIODATA0      0xC0
+#define TC3589x_GPIOMASK0      0xc1
+#define TC3589x_GPIODATA1      0xC2
+#define TC3589x_GPIOMASK1      0xc3
+#define TC3589x_GPIODATA2      0xC4
+#define TC3589x_GPIOMASK2      0xC5
+
+#define TC3589x_GPIODIR0       0xC6
+#define TC3589x_GPIODIR1       0xC7
+#define TC3589x_GPIODIR2       0xC8
+
+#define TC3589x_GPIOSYNC0      0xE6
+#define TC3589x_GPIOSYNC1      0xE7
+#define TC3589x_GPIOSYNC2      0xE8
+
+#define TC3589x_GPIOWAKE0      0xE9
+#define TC3589x_GPIOWAKE1      0xEA
+#define TC3589x_GPIOWAKE2      0xEB
+
+#define TC3589x_GPIOODM0       0xE0
+#define TC3589x_GPIOODE0       0xE1
+#define TC3589x_GPIOODM1       0xE2
+#define TC3589x_GPIOODE1       0xE3
+#define TC3589x_GPIOODM2       0xE4
+#define TC3589x_GPIOODE2       0xE5
+
+#define TC3589x_INT_GPIIRQ     0
+#define TC3589x_INT_TI0IRQ     1
+#define TC3589x_INT_TI1IRQ     2
+#define TC3589x_INT_TI2IRQ     3
+#define TC3589x_INT_ROTIRQ     5
+#define TC3589x_INT_KBDIRQ     6
+#define TC3589x_INT_PORIRQ     7
+
+#define TC3589x_NR_INTERNAL_IRQS       8
+#define TC3589x_INT_GPIO(x)    (TC3589x_NR_INTERNAL_IRQS + (x))
+
+struct tc3589x {
+       struct mutex lock;
+       struct device *dev;
+       struct i2c_client *i2c;
+
+       int irq_base;
+       int num_gpio;
+       struct tc3589x_platform_data *pdata;
+};
+
+extern int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data);
+extern int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg);
+extern int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length,
+                             u8 *values);
+extern int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
+                              const u8 *values);
+extern int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val);
+
+/*
+ * Keypad related platform specific constants
+ * These values may be modified for fine tuning
+ */
+#define TC_KPD_ROWS             0x8
+#define TC_KPD_COLUMNS          0x8
+#define TC_KPD_DEBOUNCE_PERIOD  0xA3
+#define TC_KPD_SETTLE_TIME      0xA3
+
+/**
+ * struct tc35893_platform_data - data structure for platform specific data
+ * @keymap_data:        matrix scan code table for keycodes
+ * @krow:               mask for available rows, value is 0xFF
+ * @kcol:               mask for available columns, value is 0xFF
+ * @debounce_period:    platform specific debounce time
+ * @settle_time:        platform specific settle down time
+ * @irqtype:            type of interrupt, falling or rising edge
+ * @enable_wakeup:      specifies if keypad event can wake up system from sleep
+ * @no_autorepeat:      flag for auto repetition
+ */
+struct tc3589x_keypad_platform_data {
+       const struct matrix_keymap_data *keymap_data;
+       u8                      krow;
+       u8                      kcol;
+       u8                      debounce_period;
+       u8                      settle_time;
+       unsigned long           irqtype;
+       bool                    enable_wakeup;
+       bool                    no_autorepeat;
+};
+
+/**
+ * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data
+ * @gpio_base: first gpio number assigned to TC3589x.  A maximum of
+ *            %TC3589x_NR_GPIOS GPIOs will be allocated.
+ * @setup: callback for board-specific initialization
+ * @remove: callback for board-specific teardown
+ */
+struct tc3589x_gpio_platform_data {
+       int gpio_base;
+       void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base);
+       void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base);
+};
+
+/**
+ * struct tc3589x_platform_data - TC3589x platform data
+ * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*)
+ * @irq_base: base IRQ number.  %TC3589x_NR_IRQS irqs will be used.
+ * @gpio: GPIO-specific platform data
+ * @keypad: keypad-specific platform data
+ */
+struct tc3589x_platform_data {
+       unsigned int block;
+       int irq_base;
+       struct tc3589x_gpio_platform_data *gpio;
+       const struct tc3589x_keypad_platform_data *keypad;
+};
+
+#define TC3589x_NR_GPIOS       24
+#define TC3589x_NR_IRQS                TC3589x_INT_GPIO(TC3589x_NR_GPIOS)
+
+#endif
index 5c51f367c0610166bbf6ec12d6fedc7587d7420e..add8a1b8bcf0057c3f328c51dc96a4d82ae331a5 100644 (file)
@@ -29,7 +29,7 @@ struct wm8994_ldo_pdata {
 #define WM8994_CONFIGURE_GPIO 0x8000
 
 #define WM8994_DRC_REGS 5
-#define WM8994_EQ_REGS  19
+#define WM8994_EQ_REGS  20
 
 /**
  * DRC configurations are specified with a label and a set of register
index c66fdb7d6998129701f6eaa653f1d28dd641e332..29d504d5d1c31f5698433657dd534c1500f317b2 100644 (file)
@@ -401,6 +401,7 @@ extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
 extern const struct address_space_operations nfs_file_aops;
+extern const struct address_space_operations nfs_dir_aops;
 
 static inline struct nfs_open_context *nfs_file_open_context(struct file *filp)
 {
index f8b60e7f4c44d9b652a94bca2ab8945130bdb061..d55cee73f63477a326b73cf7eb15e3e277567b14 100644 (file)
@@ -29,6 +29,7 @@
  */
 enum {
        PG_BUSY = 0,
+       PG_MAPPED,
        PG_CLEAN,
        PG_NEED_COMMIT,
        PG_NEED_RESCHED,
index ebb0c80ffd6ebb53b02fb2263e0a6ff6a634eb6a..12b2b18e50c1c321f208a83d4bbda61ce985450c 100644 (file)
@@ -230,6 +230,7 @@ enum
        LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */
        LINUX_MIB_TCPDEFERACCEPTDROP,
        LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
+       LINUX_MIB_TCPTIMEWAITOVERFLOW,          /* TCPTimeWaitOverflow */
        __LINUX_MIB_MAX
 };
 
index 2fb46bc9340d9b40617042ba8bb253754e4b6f67..ed5cdeb3604dbe6ea1fe807b33a69bf140d1622a 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef _LINUX_VIDEO_OUTPUT_H
 #define _LINUX_VIDEO_OUTPUT_H
 #include <linux/device.h>
+#include <linux/err.h>
 struct output_device;
 struct output_properties {
        int (*set_state)(struct output_device *);
@@ -34,9 +35,23 @@ struct output_device {
        struct device dev;
 };
 #define to_output_device(obj) container_of(obj, struct output_device, dev)
+#if    defined(CONFIG_VIDEO_OUTPUT_CONTROL) || defined(CONFIG_VIDEO_OUTPUT_CONTROL_MODULE)
 struct output_device *video_output_register(const char *name,
        struct device *dev,
        void *devdata,
        struct output_properties *op);
 void video_output_unregister(struct output_device *dev);
+#else
+static struct output_device *video_output_register(const char *name,
+        struct device *dev,
+        void *devdata,
+        struct output_properties *op)
+{
+       return ERR_PTR(-ENODEV);
+}
+static void video_output_unregister(struct output_device *dev)
+{
+       return;
+}
+#endif
 #endif
index a6338d039857bf6b00bcff087f974ebf46ae0875..659d968d95c54afe6df51c3289a0d2d6fb5b34ed 100644 (file)
@@ -1155,6 +1155,8 @@ extern void sk_common_release(struct sock *sk);
 /* Initialise core socket variables */
 extern void sock_init_data(struct socket *sock, struct sock *sk);
 
+extern void sk_filter_release_rcu(struct rcu_head *rcu);
+
 /**
  *     sk_filter_release - release a socket filter
  *     @fp: filter to remove
@@ -1165,7 +1167,7 @@ extern void sock_init_data(struct socket *sock, struct sock *sk);
 static inline void sk_filter_release(struct sk_filter *fp)
 {
        if (atomic_dec_and_test(&fp->refcnt))
-               kfree(fp);
+               call_rcu_bh(&fp->rcu, sk_filter_release_rcu);
 }
 
 static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
index e8cbf431c8ccfd33f76fd018e8dd64ea6dd2c8b7..75271b9a8f61bedcec5a18465b5a9ca8e84a38c7 100644 (file)
@@ -24,8 +24,15 @@ typedef unsigned int RING_IDX;
  * A ring contains as many entries as will fit, rounded down to the nearest
  * power of two (so we can mask with (size-1) to loop around).
  */
-#define __RING_SIZE(_s, _sz) \
-    (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+#define __CONST_RING_SIZE(_s, _sz)                             \
+       (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) /   \
+               sizeof(((struct _s##_sring *)0)->ring[0])))
+
+/*
+ * The same for passing in an actual pointer instead of a name tag.
+ */
+#define __RING_SIZE(_s, _sz)                                           \
+       (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
 
 /*
  * Macros to make the correct C datatypes for a new kind of ring.
index 9a2264fc42cafac30d9264d569e4e673e9617f19..a23315dc4498844c113cecc9792eabd063e1d87b 100644 (file)
@@ -1082,13 +1082,15 @@ void printk_tick(void)
 
 int printk_needs_cpu(int cpu)
 {
+       if (unlikely(cpu_is_offline(cpu)))
+               printk_tick();
        return per_cpu(printk_pending, cpu);
 }
 
 void wake_up_klogd(void)
 {
        if (waitqueue_active(&log_wait))
-               __raw_get_cpu_var(printk_pending) = 1;
+               this_cpu_write(printk_pending, 1);
 }
 
 /**
index 90db1bd1a97852e4c547c43d840b2ca624c9a773..e785b0f2aea57f362f9528fb979f15716f7f2aa4 100644 (file)
@@ -661,7 +661,7 @@ void wq_worker_waking_up(struct task_struct *task, unsigned int cpu)
 {
        struct worker *worker = kthread_data(task);
 
-       if (likely(!(worker->flags & WORKER_NOT_RUNNING)))
+       if (!(worker->flags & WORKER_NOT_RUNNING))
                atomic_inc(get_gcwq_nr_running(cpu));
 }
 
@@ -687,7 +687,7 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task,
        struct global_cwq *gcwq = get_gcwq(cpu);
        atomic_t *nr_running = get_gcwq_nr_running(cpu);
 
-       if (unlikely(worker->flags & WORKER_NOT_RUNNING))
+       if (worker->flags & WORKER_NOT_RUNNING)
                return NULL;
 
        /* this can only happen on the local cpu */
@@ -3692,7 +3692,8 @@ static int __init init_workqueues(void)
        system_nrt_wq = alloc_workqueue("events_nrt", WQ_NON_REENTRANT, 0);
        system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND,
                                            WQ_UNBOUND_MAX_ACTIVE);
-       BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq);
+       BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq ||
+              !system_unbound_wq);
        return 0;
 }
 early_initcall(init_workqueues);
index ea89840fc65fa2b499ce3c19c657e9e8a680b240..6b9aee20f2426b88024a25749402fc5ca1ff7a0a 100644 (file)
@@ -143,13 +143,18 @@ void __remove_from_page_cache(struct page *page)
 void remove_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
+       void (*freepage)(struct page *);
 
        BUG_ON(!PageLocked(page));
 
+       freepage = mapping->a_ops->freepage;
        spin_lock_irq(&mapping->tree_lock);
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (freepage)
+               freepage(page);
 }
 EXPORT_SYMBOL(remove_from_page_cache);
 
index b179abb1474ae41bff47060b5241045d3b1b12ad..50a4aa0255a0703f83c8667028afe8545d78e09a 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2462,6 +2462,7 @@ int install_special_mapping(struct mm_struct *mm,
                            unsigned long addr, unsigned long len,
                            unsigned long vm_flags, struct page **pages)
 {
+       int ret;
        struct vm_area_struct *vma;
 
        vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
@@ -2479,16 +2480,23 @@ int install_special_mapping(struct mm_struct *mm,
        vma->vm_ops = &special_mapping_vmops;
        vma->vm_private_data = pages;
 
-       if (unlikely(insert_vm_struct(mm, vma))) {
-               kmem_cache_free(vm_area_cachep, vma);
-               return -ENOMEM;
-       }
+       ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+       if (ret)
+               goto out;
+
+       ret = insert_vm_struct(mm, vma);
+       if (ret)
+               goto out;
 
        mm->total_vm += len >> PAGE_SHIFT;
 
        perf_event_mmap(vma);
 
        return 0;
+
+out:
+       kmem_cache_free(vm_area_cachep, vma);
+       return ret;
 }
 
 static DEFINE_MUTEX(mm_all_locks_mutex);
index ba887bff48c5a263c315a6ef098284df4df5bb44..3c2d5ddfa0d49f3cf31449e214d8fbd50e92ad08 100644 (file)
@@ -390,6 +390,10 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (mapping->a_ops->freepage)
+               mapping->a_ops->freepage(page);
+
        page_cache_release(page);       /* pagecache ref */
        return 1;
 failed:
index d31d7ce52c0ea2dbbf85b26019c9fdd70fab624a..9ca587c692748adbc715b440ff5aa8c89357c511 100644 (file)
@@ -494,9 +494,16 @@ static int __remove_mapping(struct address_space *mapping, struct page *page)
                spin_unlock_irq(&mapping->tree_lock);
                swapcache_free(swap, page);
        } else {
+               void (*freepage)(struct page *);
+
+               freepage = mapping->a_ops->freepage;
+
                __remove_from_page_cache(page);
                spin_unlock_irq(&mapping->tree_lock);
                mem_cgroup_uncharge_cache_page(page);
+
+               if (freepage != NULL)
+                       freepage(page);
        }
 
        return 1;
index 799c631f0fed0c1e8210d2d61e3fdf3afd27aea9..f7fa67c78766f59c0b107ece600348f401a40d57 100644 (file)
@@ -143,12 +143,13 @@ static struct class atm_class = {
        .dev_uevent             = atm_uevent,
 };
 
-int atm_register_sysfs(struct atm_dev *adev)
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent)
 {
        struct device *cdev = &adev->class_dev;
        int i, j, err;
 
        cdev->class = &atm_class;
+       cdev->parent = parent;
        dev_set_drvdata(cdev, adev);
 
        dev_set_name(cdev, "%s%d", adev->type, adev->number);
index d29e582615116a68e1f476091c6475d589401878..23f45ce6f3510fb1e9b30b58b7e52fac6a456961 100644 (file)
@@ -74,8 +74,9 @@ struct atm_dev *atm_dev_lookup(int number)
 }
 EXPORT_SYMBOL(atm_dev_lookup);
 
-struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
-                                int number, unsigned long *flags)
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+                                const struct atmdev_ops *ops, int number,
+                                unsigned long *flags)
 {
        struct atm_dev *dev, *inuse;
 
@@ -115,7 +116,7 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
                goto out_fail;
        }
 
-       if (atm_register_sysfs(dev) < 0) {
+       if (atm_register_sysfs(dev, parent) < 0) {
                pr_err("atm_register_sysfs failed for dev %s\n", type);
                atm_proc_dev_deregister(dev);
                goto out_fail;
index 126fb1840dfbb2ddd853602892e1a5e740bd90ac..521431e305073acc8c418c56317c09bb13b4731d 100644 (file)
@@ -42,6 +42,6 @@ static inline void atm_proc_dev_deregister(struct atm_dev *dev)
 
 #endif /* CONFIG_PROC_FS */
 
-int atm_register_sysfs(struct atm_dev *adev);
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent);
 void atm_unregister_sysfs(struct atm_dev *adev);
 #endif
index d0927d1fdadaba4887dbac40064c4328541b9b00..66b9e5c0523a2211450cece91d5cf217fbd4722b 100644 (file)
@@ -882,7 +882,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
        int lm = 0;
 
        if (type != SCO_LINK && type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
@@ -908,7 +908,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
        BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
 
        if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        if (!status) {
                struct sco_conn *conn;
@@ -927,7 +927,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
        BT_DBG("hcon %p reason %d", hcon, reason);
 
        if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return 0;
+               return -EINVAL;
 
        sco_conn_del(hcon, bt_err(reason));
 
index c1ee800bc080c3faf33033e1659021a0a356f7ce..ae21a0d3c4a2a4566c3792476e07ce0d2d2ece38 100644 (file)
@@ -589,23 +589,16 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
 EXPORT_SYMBOL(sk_chk_filter);
 
 /**
- *     sk_filter_rcu_release - Release a socket filter by rcu_head
+ *     sk_filter_release_rcu - Release a socket filter by rcu_head
  *     @rcu: rcu_head that contains the sk_filter to free
  */
-static void sk_filter_rcu_release(struct rcu_head *rcu)
+void sk_filter_release_rcu(struct rcu_head *rcu)
 {
        struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
 
-       sk_filter_release(fp);
-}
-
-static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp)
-{
-       unsigned int size = sk_filter_len(fp);
-
-       atomic_sub(size, &sk->sk_omem_alloc);
-       call_rcu_bh(&fp->rcu, sk_filter_rcu_release);
+       kfree(fp);
 }
+EXPORT_SYMBOL(sk_filter_release_rcu);
 
 /**
  *     sk_attach_filter - attach a socket filter
@@ -649,7 +642,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
        rcu_assign_pointer(sk->sk_filter, fp);
 
        if (old_fp)
-               sk_filter_delayed_uncharge(sk, old_fp);
+               sk_filter_uncharge(sk, old_fp);
        return 0;
 }
 EXPORT_SYMBOL_GPL(sk_attach_filter);
@@ -663,7 +656,7 @@ int sk_detach_filter(struct sock *sk)
                                           sock_owned_by_user(sk));
        if (filter) {
                rcu_assign_pointer(sk->sk_filter, NULL);
-               sk_filter_delayed_uncharge(sk, filter);
+               sk_filter_uncharge(sk, filter);
                ret = 0;
        }
        return ret;
index 0ae6c22da85b2a3516980691c8fbcf2f7228e3d6..c19bb4ee405ede196271ac9af5452dd21525fe2e 100644 (file)
@@ -96,11 +96,13 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
        struct phy_device *phydev;
        unsigned int type;
 
-       skb_push(skb, ETH_HLEN);
+       if (skb_headroom(skb) < ETH_HLEN)
+               return false;
+       __skb_push(skb, ETH_HLEN);
 
        type = classify(skb);
 
-       skb_pull(skb, ETH_HLEN);
+       __skb_pull(skb, ETH_HLEN);
 
        switch (type) {
        case PTP_CLASS_V1_IPV4:
index 13992e1d2726cd29f9d84d9f782d0eb8cf3fbd5d..15dcc1a586b4a312ee877e78b4e72f1a5e9631e2 100644 (file)
@@ -661,8 +661,10 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
        err = 0;
        switch (cmd) {
        case SIOCSIFADDR:
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
+               if (!capable(CAP_NET_ADMIN)) {
+                       err = -EPERM;
+                       break;
+               }
 
                edev = dev->ec_ptr;
                if (edev == NULL) {
@@ -849,9 +851,13 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
 {
        struct iphdr *ip = ip_hdr(skb);
        unsigned char stn = ntohl(ip->saddr) & 0xff;
+       struct dst_entry *dst = skb_dst(skb);
+       struct ec_device *edev = NULL;
        struct sock *sk = NULL;
        struct sk_buff *newskb;
-       struct ec_device *edev = skb->dev->ec_ptr;
+
+       if (dst)
+               edev = dst->dev->ec_ptr;
 
        if (! edev)
                goto bad;
index 1b48eb1ed4531d3fd037e7ee9aa6367b6cb575f3..b14ec7d03b6e70b9a5a1823261ac18cb40462035 100644 (file)
@@ -253,6 +253,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP),
        SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP),
        SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
+       SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
        SNMP_MIB_SENTINEL
 };
 
index 43cf901d765970b6a1a80f167a80ec285a8397b6..a66735f75963582ebc2243e37fd12ca4604be678 100644 (file)
@@ -347,7 +347,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
                 * socket up.  We've got bigger problems than
                 * non-graceful socket closings.
                 */
-               LIMIT_NETDEBUG(KERN_INFO "TCP: time wait bucket table overflow\n");
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW);
        }
 
        tcp_update_metrics(sk);
index 05b1ecf367632763cbdb1f3bfe0e74c9c4d20c0c..61c2463e2753f809c12f31967e7fa189e41e1f54 100644 (file)
@@ -231,11 +231,10 @@ void tcp_select_initial_window(int __space, __u32 mss,
                /* when initializing use the value from init_rcv_wnd
                 * rather than the default from above
                 */
-               if (init_rcv_wnd &&
-                   (*rcv_wnd > init_rcv_wnd * mss))
-                       *rcv_wnd = init_rcv_wnd * mss;
-               else if (*rcv_wnd > init_cwnd * mss)
-                       *rcv_wnd = init_cwnd * mss;
+               if (init_rcv_wnd)
+                       *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
+               else
+                       *rcv_wnd = min(*rcv_wnd, init_cwnd * mss);
        }
 
        /* Set the clamp no higher than max representable value */
@@ -386,27 +385,30 @@ struct tcp_out_options {
  */
 static u8 tcp_cookie_size_check(u8 desired)
 {
-       if (desired > 0) {
+       int cookie_size;
+
+       if (desired > 0)
                /* previously specified */
                return desired;
-       }
-       if (sysctl_tcp_cookie_size <= 0) {
+
+       cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size);
+       if (cookie_size <= 0)
                /* no default specified */
                return 0;
-       }
-       if (sysctl_tcp_cookie_size <= TCP_COOKIE_MIN) {
+
+       if (cookie_size <= TCP_COOKIE_MIN)
                /* value too small, specify minimum */
                return TCP_COOKIE_MIN;
-       }
-       if (sysctl_tcp_cookie_size >= TCP_COOKIE_MAX) {
+
+       if (cookie_size >= TCP_COOKIE_MAX)
                /* value too large, specify maximum */
                return TCP_COOKIE_MAX;
-       }
-       if (0x1 & sysctl_tcp_cookie_size) {
+
+       if (cookie_size & 1)
                /* 8-bit multiple, illegal, fix it */
-               return (u8)(sysctl_tcp_cookie_size + 0x1);
-       }
-       return (u8)sysctl_tcp_cookie_size;
+               cookie_size++;
+
+       return (u8)cookie_size;
 }
 
 /* Write previously computed TCP options to the packet.
@@ -1513,6 +1515,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
        struct tcp_sock *tp = tcp_sk(sk);
        const struct inet_connection_sock *icsk = inet_csk(sk);
        u32 send_win, cong_win, limit, in_flight;
+       int win_divisor;
 
        if (TCP_SKB_CB(skb)->flags & TCPHDR_FIN)
                goto send_now;
@@ -1544,13 +1547,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
        if ((skb != tcp_write_queue_tail(sk)) && (limit >= skb->len))
                goto send_now;
 
-       if (sysctl_tcp_tso_win_divisor) {
+       win_divisor = ACCESS_ONCE(sysctl_tcp_tso_win_divisor);
+       if (win_divisor) {
                u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache);
 
                /* If at least some fraction of a window is available,
                 * just use it.
                 */
-               chunk /= sysctl_tcp_tso_win_divisor;
+               chunk /= win_divisor;
                if (limit >= chunk)
                        goto send_now;
        } else {
index 23cc8e1ce8d4995a551ca93d98434e9150ad1740..93b7a933a7758254ed70ed849d333ad4d19114a7 100644 (file)
@@ -4021,11 +4021,11 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
                kfree_skb(skb);
                goto errout;
        }
-       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFINFO, NULL, GFP_ATOMIC);
        return;
 errout:
        if (err < 0)
-               rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+               rtnl_set_sk_err(net, RTNLGRP_IPV6_IFINFO, err);
 }
 
 static inline size_t inet6_prefix_nlmsg_size(void)
index 2a59610c2a582ed885ae756729b58da00e6f324f..70e891a20fb9258686b9d9914e6694a3837d0acb 100644 (file)
@@ -1175,6 +1175,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
                                sizeof (struct ipv6hdr);
 
                        dev->mtu = rt->rt6i_dev->mtu - sizeof (struct ipv6hdr);
+                       if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+                               dev->mtu-=8;
 
                        if (dev->mtu < IPV6_MIN_MTU)
                                dev->mtu = IPV6_MIN_MTU;
@@ -1363,12 +1365,17 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
+       struct ip6_tnl *t;
+
        dev->netdev_ops = &ip6_tnl_netdev_ops;
        dev->destructor = ip6_dev_free;
 
        dev->type = ARPHRD_TUNNEL6;
        dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr);
        dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
+       t = netdev_priv(dev);
+       if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+               dev->mtu-=8;
        dev->flags |= IFF_NOARP;
        dev->addr_len = sizeof(struct in6_addr);
        dev->features |= NETIF_F_NETNS_LOCAL;
index d6bfaec3bbbf1a91701fd31616757af1a565bb41..8c4d00c7cd2bb030c194c19e00b5455d2cddf3df 100644 (file)
@@ -606,8 +606,9 @@ static int ipip6_rcv(struct sk_buff *skb)
                return 0;
        }
 
-       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+       /* no tunnel matched,  let upstream know, ipsec may handle it */
        rcu_read_unlock();
+       return 1;
 out:
        kfree_skb(skb);
        return 0;
index 0bf6a59545ab9439f3ab7126539cd9aef419b752..522e219f3558a3e0e3ad70f27e2de3d09ed8f543 100644 (file)
@@ -674,4 +674,8 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 MODULE_DESCRIPTION("L2TP over IP");
 MODULE_VERSION("1.0");
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, SOCK_DGRAM, IPPROTO_L2TP);
+
+/* Use the value of SOCK_DGRAM (2) directory, because __stringify does't like
+ * enums
+ */
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
index 582612998211d24aa8d4aea919eed1ba1e994db3..e35dbe55f5201c7a8b4b61ffe382766e4abadcb8 100644 (file)
@@ -317,8 +317,9 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                goto out;
        rc = -ENODEV;
        rtnl_lock();
+       rcu_read_lock();
        if (sk->sk_bound_dev_if) {
-               llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
+               llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
                if (llc->dev) {
                        if (!addr->sllc_arphrd)
                                addr->sllc_arphrd = llc->dev->type;
@@ -329,13 +330,13 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                            !llc_mac_match(addr->sllc_mac,
                                           llc->dev->dev_addr)) {
                                rc = -EINVAL;
-                               dev_put(llc->dev);
                                llc->dev = NULL;
                        }
                }
        } else
                llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd,
                                           addr->sllc_mac);
+       rcu_read_unlock();
        rtnl_unlock();
        if (!llc->dev)
                goto out;
index 902b03ee8f60789bab002691e2db69d1f8c12cf4..54fb4a0e76f03d835c6038cffeabf18874cb2d59 100644 (file)
@@ -2247,6 +2247,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
                break;
        case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
        case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+               if (is_multicast_ether_addr(mgmt->da) &&
+                   !is_broadcast_ether_addr(mgmt->da))
+                       return RX_DROP_MONITOR;
+
                /* process only for station */
                if (sdata->vif.type != NL80211_IFTYPE_STATION)
                        return RX_DROP_MONITOR;
@@ -2741,6 +2745,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
                                return;
+                       goto out;
                }
        }
 
@@ -2780,6 +2785,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                        return;
        }
 
+ out:
        dev_kfree_skb(skb);
 }
 
index 96c594309506432b897b4ab8c749aed4cb3c1349..7a637b80a62ef7a8d00d49285d9d6995b4083d9e 100644 (file)
@@ -1587,7 +1587,12 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                                                list) {
                                if (!ieee80211_sdata_running(tmp_sdata))
                                        continue;
-                               if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
+                               if (tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_MONITOR ||
+                                   tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_AP_VLAN ||
+                                       tmp_sdata->vif.type ==
+                                   NL80211_IFTYPE_WDS)
                                        continue;
                                if (compare_ether_addr(tmp_sdata->vif.addr,
                                                       hdr->addr2) == 0) {
@@ -1732,15 +1737,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        int nh_pos, h_pos;
        struct sta_info *sta = NULL;
        u32 sta_flags = 0;
+       struct sk_buff *tmp_skb;
 
        if (unlikely(skb->len < ETH_HLEN)) {
                ret = NETDEV_TX_OK;
                goto fail;
        }
 
-       nh_pos = skb_network_header(skb) - skb->data;
-       h_pos = skb_transport_header(skb) - skb->data;
-
        /* convert Ethernet header to proper 802.11 header (based on
         * operation mode) */
        ethertype = (skb->data[12] << 8) | skb->data[13];
@@ -1913,6 +1916,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                goto fail;
        }
 
+       /*
+        * If the skb is shared we need to obtain our own copy.
+        */
+       if (skb_shared(skb)) {
+               tmp_skb = skb;
+               skb = skb_copy(skb, GFP_ATOMIC);
+               kfree_skb(tmp_skb);
+
+               if (!skb) {
+                       ret = NETDEV_TX_OK;
+                       goto fail;
+               }
+       }
+
        hdr.frame_control = fc;
        hdr.duration_id = 0;
        hdr.seq_ctrl = 0;
@@ -1931,6 +1948,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                encaps_len = 0;
        }
 
+       nh_pos = skb_network_header(skb) - skb->data;
+       h_pos = skb_transport_header(skb) - skb->data;
+
        skb_pull(skb, skip_header_bytes);
        nh_pos -= skip_header_bytes;
        h_pos -= skip_header_bytes;
index 6bd554323a342d4db49be267766b87492bd2e584..0b9ee34ad35ceb31ff764baf9cec73fba010f55b 100644 (file)
@@ -2932,6 +2932,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
        struct sctp_association *asoc = NULL;
        struct sctp_setpeerprim prim;
        struct sctp_chunk       *chunk;
+       struct sctp_af          *af;
        int                     err;
 
        sp = sctp_sk(sk);
@@ -2959,6 +2960,13 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
        if (!sctp_state(asoc, ESTABLISHED))
                return -ENOTCONN;
 
+       af = sctp_get_af_specific(prim.sspp_addr.ss_family);
+       if (!af)
+               return -EINVAL;
+
+       if (!af->addr_valid((union sctp_addr *)&prim.sspp_addr, sp, NULL))
+               return -EADDRNOTAVAIL;
+
        if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
                return -EADDRNOTAVAIL;
 
index 3ca2fd9e37200e3e12f6606065acb8c982f25528..088fb3fd45e00f3fa5d55e3e374c8751e60d225b 100644 (file)
@@ -732,6 +732,21 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
        return ret;
 }
 
+/**
+ * kernel_recvmsg - Receive a message from a socket (kernel space)
+ * @sock:       The socket to receive the message from
+ * @msg:        Received message
+ * @vec:        Input s/g array for message data
+ * @num:        Size of input s/g array
+ * @size:       Number of bytes to read
+ * @flags:      Message flags (MSG_DONTWAIT, etc...)
+ *
+ * On return the msg structure contains the scatter/gather array passed in the
+ * vec argument. The array is modified so that it consists of the unfilled
+ * portion of the original array.
+ *
+ * The returned value is the total number of bytes received, or an error.
+ */
 int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
                   struct kvec *vec, size_t num, size_t size, int flags)
 {
index ea2ff78dcf7b7ec4f2555210af82379017e6e291..3f2c5559ca1a49a496b9d531625c1e175fb029c8 100644 (file)
@@ -212,6 +212,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
        spin_lock(&svc_xprt_class_lock);
        list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
                struct svc_xprt *newxprt;
+               unsigned short newport;
 
                if (strcmp(xprt_name, xcl->xcl_name))
                        continue;
@@ -230,8 +231,9 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                spin_lock_bh(&serv->sv_lock);
                list_add(&newxprt->xpt_list, &serv->sv_permsocks);
                spin_unlock_bh(&serv->sv_lock);
+               newport = svc_xprt_local_port(newxprt);
                clear_bit(XPT_BUSY, &newxprt->xpt_flags);
-               return svc_xprt_local_port(newxprt);
+               return newport;
        }
  err:
        spin_unlock(&svc_xprt_class_lock);
@@ -425,8 +427,13 @@ void svc_xprt_received(struct svc_xprt *xprt)
 {
        BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
        xprt->xpt_pool = NULL;
+       /* As soon as we clear busy, the xprt could be closed and
+        * 'put', so we need a reference to call svc_xprt_enqueue with:
+        */
+       svc_xprt_get(xprt);
        clear_bit(XPT_BUSY, &xprt->xpt_flags);
        svc_xprt_enqueue(xprt);
+       svc_xprt_put(xprt);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_received);
 
index 73e7b954ad288229df4d03bc164f07da183444cc..b25c6463c3e996cf536454603f4f0257f3b8b51c 100644 (file)
@@ -394,6 +394,7 @@ void __exit x25_link_free(void)
        list_for_each_safe(entry, tmp, &x25_neigh_list) {
                nb = list_entry(entry, struct x25_neigh, node);
                __x25_remove_neigh(nb);
+               dev_put(nb->dev);
        }
        write_unlock_bh(&x25_neigh_list_lock);
 }
index eb96ce52f1789dd881116e76a08169189b50f02c..220ebc05c7afc6b602785f6e402d44098cc0bd8d 100644 (file)
@@ -1268,7 +1268,7 @@ struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
 
        return xc;
 error:
-       kfree(xc);
+       xfrm_state_put(xc);
        return NULL;
 }
 EXPORT_SYMBOL(xfrm_state_migrate);
index cb0c23a6b473e07bd9d768f9430e7cde2342639c..4a663471dadc1e1e00d712bd5656577aeba56984 100644 (file)
@@ -189,6 +189,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
        a->channels = GRAB_BITS(buf, 0, 0, 3);
        a->channels++;
 
+       a->sample_bits = 0;
+       a->max_bitrate = 0;
+
        a->format = GRAB_BITS(buf, 0, 3, 4);
        switch (a->format) {
        case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
@@ -198,7 +201,6 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 
        case AUDIO_CODING_TYPE_LPCM:
                val = GRAB_BITS(buf, 2, 0, 3);
-               a->sample_bits = 0;
                for (i = 0; i < 3; i++)
                        if (val & (1 << i))
                                a->sample_bits |= cea_sample_sizes[i + 1];
@@ -598,24 +600,19 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
 {
        int i;
 
-       pcm->rates = 0;
-       pcm->formats = 0;
-       pcm->maxbps = 0;
-       pcm->channels_min = -1;
-       pcm->channels_max = 0;
+       /* assume basic audio support (the basic audio flag is not in ELD;
+        * however, all audio capable sinks are required to support basic
+        * audio) */
+       pcm->rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+       pcm->formats = SNDRV_PCM_FMTBIT_S16_LE;
+       pcm->maxbps = 16;
+       pcm->channels_max = 2;
        for (i = 0; i < eld->sad_count; i++) {
                struct cea_sad *a = &eld->sad[i];
                pcm->rates |= a->rates;
-               if (a->channels < pcm->channels_min)
-                       pcm->channels_min = a->channels;
                if (a->channels > pcm->channels_max)
                        pcm->channels_max = a->channels;
                if (a->format == AUDIO_CODING_TYPE_LPCM) {
-                       if (a->sample_bits & AC_SUPPCM_BITS_16) {
-                               pcm->formats |= SNDRV_PCM_FMTBIT_S16_LE;
-                               if (pcm->maxbps < 16)
-                                       pcm->maxbps = 16;
-                       }
                        if (a->sample_bits & AC_SUPPCM_BITS_20) {
                                pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
                                if (pcm->maxbps < 20)
@@ -635,7 +632,6 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
        /* restrict the parameters by the values the codec provides */
        pcm->rates &= codec_pars->rates;
        pcm->formats &= codec_pars->formats;
-       pcm->channels_min = max(pcm->channels_min, codec_pars->channels_min);
        pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
        pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
 }
index 21aa9b0e28f6cb466a81a4d1e4c48622c71f89c9..b030c8eba21fdc618fe0b5bfb32cf5b156c39bba 100644 (file)
@@ -2296,6 +2296,7 @@ static int azx_dev_free(struct snd_device *device)
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1025, 0x026f, "Acer Aspire 5538", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
index 846d1ead47fdf1c184fb92f37ae1faf099ec45af..76bd58a0e2b637e2c17a79cc94ab54e0747de227 100644 (file)
@@ -2116,8 +2116,8 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        struct conexant_spec *spec = codec->spec;
        unsigned int pinctl;
 
-       snd_printdd("CXT5066: update speaker, hp_present=%d\n",
-               spec->hp_present);
+       snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
+                   spec->hp_present, spec->cur_eapd);
 
        /* Port A (HP) */
        pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
@@ -2125,11 +2125,20 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
                        pinctl);
 
        /* Port D (HP/LO) */
-       pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
-               ? spec->port_d_mode : 0;
-       /* Mute if Port A is connected on Thinkpad */
-       if (spec->thinkpad && (spec->hp_present & 1))
-               pinctl = 0;
+       if (spec->dell_automute) {
+               /* DELL AIO Port Rule: PortA>  PortD>  IntSpk */
+               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
+                       ? PIN_OUT : 0;
+       } else if (spec->thinkpad) {
+               if (spec->cur_eapd)
+                       pinctl = spec->port_d_mode;
+               /* Mute dock line-out if Port A (laptop HP) is present */
+               if (spec->hp_present&  1)
+                       pinctl = 0;
+       } else {
+               pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
+                       ? spec->port_d_mode : 0;
+       }
        snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
 
@@ -2137,14 +2146,6 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
        snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
-
-       if (spec->dell_automute) {
-               /* DELL AIO Port Rule: PortA > PortD > IntSpk */
-               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
-                       ? PIN_OUT : 0;
-               snd_hda_codec_write(codec, 0x1c, 0,
-                       AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
-       }
 }
 
 /* turn on/off EAPD (+ mute HP) as a master switch */
@@ -3095,8 +3096,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
-       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
-                     CXT5066_DELL_LAPTOP),
+       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
@@ -3109,6 +3109,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD),
index d3e49aa5b9ecd42f6db6f5892319e6602ad9b7ab..31df7747990d0be6690a520321a0498c9caba349 100644 (file)
@@ -834,7 +834,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
                        return -ENODEV;
        } else {
                /* fallback to the codec default */
-               hinfo->channels_min = codec_pars->channels_min;
                hinfo->channels_max = codec_pars->channels_max;
                hinfo->rates = codec_pars->rates;
                hinfo->formats = codec_pars->formats;
index 8fddc9d08726670c8d67dc1ce9f31dd1f82a56c4..2d7d7de8498a7947bb9c6180bc757017535c343c 100644 (file)
@@ -4595,6 +4595,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
        SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
        SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
+       SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
        SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
index a2e0ed59b3769f0b7d73024a6e4740338b1ccb81..879dff2714dd3c522211dbac3c636a5191d8ce4b 100644 (file)
@@ -491,16 +491,16 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
                paifa |= 0x8;
                break;
        case SNDRV_PCM_FORMAT_S20_3LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_20;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_24;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               paifa |= 0x10;
-               paifb |= WM8580_AIF_LENGTH_24;
+               paifa |= 0x0;
+               paifb |= WM8580_AIF_LENGTH_32;
                break;
        default:
                return -EINVAL;
index e8092745a207674caaf4351d815870e7367b4003..1304ca91a11c708c567f69c45052c95f1f7be17e 100644 (file)
@@ -3339,7 +3339,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
        int mask;
        int active;
 
-       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
 
        active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
        active &= ~mask;
index 19ca782ac970f1956243862534e5df1df12a3113..0e24092722c39522d85980a71f8a3727d01cf63f 100644 (file)
@@ -293,7 +293,7 @@ SOC_DOUBLE_R("Speaker Switch",
 SOC_DOUBLE_R("Speaker ZC Switch",
             WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
             7, 1, 0),
-SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
+SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
               spkboost_tlv),
 SOC_ENUM("Speaker Reference", speaker_ref),
 SOC_ENUM("Speaker Mode", speaker_mode),
index 441285ade024ff33589cd22204ef5cb82a1f14ea..85b7d548f1675f14c1a2065bbcffcf7d229a2e27 100644 (file)
@@ -1619,12 +1619,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 #ifdef CONFIG_SND_SOC_AC97_BUS
        /* register any AC97 codecs */
        for (i = 0; i < card->num_rtd; i++) {
-                       ret = soc_register_ac97_dai_link(&card->rtd[i]);
-                       if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
-                               goto probe_dai_err;
-                       }
+               ret = soc_register_ac97_dai_link(&card->rtd[i]);
+               if (ret < 0) {
+                       printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+                       while (--i >= 0)
+                               soc_unregister_ac97_dai_link(&card->rtd[i]);
+                       goto probe_dai_err;
                }
+       }
 #endif
 
        card->instantiated = 1;
@@ -3072,7 +3074,9 @@ int snd_soc_register_dais(struct device *dev,
                pr_debug("Registered DAI '%s'\n", dai->name);
        }
 
+       mutex_lock(&client_mutex);
        snd_soc_instantiate_cards();
+       mutex_unlock(&client_mutex);
        return 0;
 
 err:
index e2c2de201eecafc5490caba7637f0eefbcbc0b46..564491fa18b27838dd79125954bc744f51f7fe2c 100644 (file)
@@ -197,7 +197,7 @@ static void sig_atexit(void)
        if (child_pid > 0)
                kill(child_pid, SIGTERM);
 
-       if (signr == -1)
+       if (signr == -1 || signr == SIGUSR1)
                return;
 
        signal(signr, SIG_DFL);
@@ -515,6 +515,7 @@ static int __cmd_record(int argc, const char **argv)
        atexit(sig_atexit);
        signal(SIGCHLD, sig_handler);
        signal(SIGINT, sig_handler);
+       signal(SIGUSR1, sig_handler);
 
        if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
                perror("failed to create pipes");
@@ -606,6 +607,7 @@ static int __cmd_record(int argc, const char **argv)
                        execvp(argv[0], (char **)argv);
 
                        perror(argv[0]);
+                       kill(getppid(), SIGUSR1);
                        exit(-1);
                }
 
@@ -762,7 +764,7 @@ static int __cmd_record(int argc, const char **argv)
                }
        }
 
-       if (quiet)
+       if (quiet || signr == SIGUSR1)
                return 0;
 
        fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
index d7e67b167ea338a28fed519260f1069dd8e92cf9..64a85bafde63a1c6f05451a32b31eec521c799d9 100644 (file)
@@ -946,11 +946,16 @@ perf_header__find_attr(u64 id, struct perf_header *header)
 
        /*
         * We set id to -1 if the data file doesn't contain sample
-        * ids. Check for this and avoid walking through the entire
-        * list of ids which may be large.
+        * ids. This can happen when the data file contains one type
+        * of event and in that case, the header can still store the
+        * event attribute information. Check for this and avoid
+        * walking through the entire list of ids which may be large.
         */
-       if (id == -1ULL)
+       if (id == -1ULL) {
+               if (header->attrs > 0)
+                       return &header->attr[0]->attr;
                return NULL;
+       }
 
        for (i = 0; i < header->attrs; i++) {
                struct perf_header_attr *attr = header->attr[i];
index 0500895a45af530bf52dc949551ed73690978c61..d628c8d1cf5ec11111ab3b750da0d14f6d8fff7f 100644 (file)
@@ -532,7 +532,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
        struct machine *machine = kmaps->machine;
        struct map *curr_map = map;
        struct symbol *pos;
-       int count = 0;
+       int count = 0, moved = 0;       
        struct rb_root *root = &self->symbols[map->type];
        struct rb_node *next = rb_first(root);
        int kernel_range = 0;
@@ -590,6 +590,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
                        char dso_name[PATH_MAX];
                        struct dso *dso;
 
+                       if (count == 0) {
+                               curr_map = map;
+                               goto filter_symbol;
+                       }
+
                        if (self->kernel == DSO_TYPE_GUEST_KERNEL)
                                snprintf(dso_name, sizeof(dso_name),
                                        "[guest.kernel].%d",
@@ -615,7 +620,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
                        map_groups__insert(kmaps, curr_map);
                        ++kernel_range;
                }
-
+filter_symbol:
                if (filter && filter(curr_map, pos)) {
 discard_symbol:                rb_erase(&pos->rb_node, root);
                        symbol__delete(pos);
@@ -623,8 +628,9 @@ discard_symbol:             rb_erase(&pos->rb_node, root);
                        if (curr_map != map) {
                                rb_erase(&pos->rb_node, root);
                                symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
-                       }
-                       count++;
+                               ++moved;
+                       } else
+                               ++count;
                }
        }
 
@@ -634,7 +640,7 @@ discard_symbol:             rb_erase(&pos->rb_node, root);
                dso__set_loaded(curr_map->dso, curr_map->type);
        }
 
-       return count;
+       return count + moved;
 }
 
 int dso__load_kallsyms(struct dso *self, const char *filename,
@@ -2125,14 +2131,55 @@ static struct dso *machine__create_kernel(struct machine *self)
        return kernel;
 }
 
+struct process_args {
+       u64 start;
+};
+
+static int symbol__in_kernel(void *arg, const char *name,
+                            char type __used, u64 start)
+{
+       struct process_args *args = arg;
+
+       if (strchr(name, '['))
+               return 0;
+
+       args->start = start;
+       return 1;
+}
+
+/* Figure out the start address of kernel map from /proc/kallsyms */
+static u64 machine__get_kernel_start_addr(struct machine *machine)
+{
+       const char *filename;
+       char path[PATH_MAX];
+       struct process_args args;
+
+       if (machine__is_host(machine)) {
+               filename = "/proc/kallsyms";
+       } else {
+               if (machine__is_default_guest(machine))
+                       filename = (char *)symbol_conf.default_guest_kallsyms;
+               else {
+                       sprintf(path, "%s/proc/kallsyms", machine->root_dir);
+                       filename = path;
+               }
+       }
+
+       if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
+               return 0;
+
+       return args.start;
+}
+
 int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
 {
        enum map_type type;
+       u64 start = machine__get_kernel_start_addr(self);
 
        for (type = 0; type < MAP__NR_TYPES; ++type) {
                struct kmap *kmap;
 
-               self->vmlinux_maps[type] = map__new2(0, kernel, type);
+               self->vmlinux_maps[type] = map__new2(start, kernel, type);
                if (self->vmlinux_maps[type] == NULL)
                        return -1;